Метод __enter__
никогда не дает никаких аргументов, поэтому за пределами self
ваша подпись не должна иметь никаких других.
Вы должны переместить эти аргументы __init__
методы вместо:
class FooBar(object):
def __init__(self, param1, param2):
# do something here ...
def __enter__(self):
# something else, perhaps return self
Создание экземпляра FooBar()
является отдельным этапом. with
вызывает __enter__
на результат вашего выражения mymod.FooBar("hello", 123)
, само выражение не переведено на звонок __enter__
.
Если бы это было, вы не могли использовать его, как это, но вы можете:
cm = mymod.FooBar("hello", 123)
with cm as x:
# do something here with x, which is the return value of cm.__enter__()
Обратите внимание, что x
назначается независимо cm.__enter__()
возвращается; вы можете вернуть self
от __enter__
или вы можете вернуть что-то совершенно другое.
Ожидаемые методы __enter__
и __exit__
задокументированы в With Statement Context Managers section модельной документации Python данных:
object.__enter__(self)
Enter the runtime context related to this object. The with
statement will bind this method’s return value to the target(s) specified in the as
clause of the statement, if any.
, а также в Content Manager Types section из встроенных типов документации:
contextmanager.__enter__()
Enter the runtime context and return either this object or another object related to the runtime context. The value returned by this method is bound to the identifier in the as
clause of with
statements using this context manager.
An example of a context manager that returns itself is a file object. File objects return themselves from __enter__()
to allow open()
to be used as the context expression in a with
statement.
Если вас интересуют точные взаимодействия, см. Первоначальное предложение: PEP 343 -- The "with" Statement; из раздела спецификации вы можете увидеть, что with EXPR as VAR: BLOCK
заявления делает под капотом:
mgr = (EXPR)
exit = type(mgr).__exit__ # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
try:
VAR = value # Only if "as VAR" is present
BLOCK
except:
# The exceptional case is handled here
exc = False
if not exit(mgr, *sys.exc_info()):
raise
# The exception is swallowed if exit() returns true
finally:
# The normal and non-local-goto cases are handled here
if exc:
exit(mgr, None, None, None)
Обратите внимание на mgr = (EXPR)
части; в вашем случае, mymod.FooBar("hello", 123)
- эта часть. Также обратите внимание, что (EXPR)
, __enter__
и __exit__
здесь не защищены 'try..except
, исключения, поднятые в выражении или при входе или выходе, равны , а не, обработанный менеджером контекста!
Но мне нужно передать params в ctor (constructor), чтобы создать допустимый объект –
@HomunculusReticulli: yes, но '__enter__' is * не является конструктором *. –
Учитывая, ваш очень высокий балл, могу ли я быть смелым, чтобы спросить вас, уверены ли вы в этом. Я всегда думал (читал где-нибудь?), Что оператор with ** создает экземпляр ** объекта (в других словах это был просто синтаксический сахар для ctor), аналогично __exit__ был аналогичен dtor. Казалось бы, большие участки моего кода ошибочны, если это так. –