В принятом ответе (который я считаю неверным) говорится, что вы НЕ МОЖЕТЕ, и вместо этого вы должны это сделать;
class Comedian:
def __init__(self, *jokes):
self.jokes = jokes
def __enter__(self):
jokes = self.jokes
#say some funny jokes
return self
..и хотя это часто то, что вы бы сделали, это не всегда лучшее решение или даже решение, и это определенно не единственное решение!..
Я предполагаю, что вы хотите иметь возможность сделать что-то похожее на;
funny_object = Comedian()
with funny_object('this is a joke') as humor:
humor.say_something_funny()
Если это так, и это не сложнее, то вы можете просто сделать;
class Comedian:
def __enter__(self):
jokes = self.jokes
#say some funny jokes
return self
def __call__(self, *jokes):
self.jokes = jokes
.. Таким образом, вы по-прежнему можете инициализировать объект с любыми аргументами, которые хотите, и делать с объектом любые другие действия, как обычно, но когда вы переходите к использованию объекта в качестве менеджера контекста, вы сначала вызываете его вызов и настройте некоторые аргументы для менеджера контекста.
Здесь важно точно понимать, как контекстные менеджеры работают в Python.
В Python менеджер контекста — это любой объект, определяющий метод enter. Этот метод вызывается автоматически, когда вы это делаете;
with object as alias:
alias.do_stuff()
..
..Обратите внимание, что у объекта нет пары "()" после него, это неявный вызов функции, и он не принимает никаких аргументов.
Возможно, вам пришла в голову идея передавать аргументы для enter from;
with open(filename) as file:
"do stuff with file..
Но это отличается от переопределения enter, поскольку «open» — это не объект, а функция.
Хорошее упражнение — открыть интерактивную консоль Python и ввести «open» + [ENTER]
>>> open
<built-in function open>
"open" - это не объект диспетчера контекста, а функция. У него вообще нет метода enter, вместо этого он определяется следующим образом;
@contextmanager
def open(..):
...
.. вы можете определить свои собственные функции контекстного менеджера таким же образом, вы даже можете переопределить определение «открыть».
ИМО, однако, лучше всего, если вам нужно создать объект, а затем использовать его в качестве диспетчера контекста с аргументами (... что я делаю), это дать объекту метод, который возвращает временный объект, который определяет введите метод, например;
class Comedian:
def context(audience):
class Roaster:
context = audience
def __enter__(self):
audience = self.__class__.context
# a comedian needs to know his/her audience.
return Roaster(audience)
funny_thing = Comedian()
with funny_thing.context('young people') as roaster:
roaster.roast('old people')
Порядок цепочки вызовов в этом примере: Comedian.init() -> Comedian.context(args) -> Roaster.enter()
Я чувствовал, что этот ответ отсутствует в лоте, поэтому я добавил его.
person
Vinzent
schedule
20.05.2020