接受的答案(我认为这是不正确的)表明您不能,而是应该这样做;
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 中,上下文管理器是定义输入方法的任何对象。当您这样做时,会自动调用此方法;
with object as alias:
alias.do_stuff()
..
..注意 object 后面没有几个“()”,它是一个隐式函数调用,它不带任何参数。
您可能已经想到传递参数以从中输入;
with open(filename) as file:
"do stuff with file..
但这与覆盖enter不同,因为“open”不是一个对象,而是一个函数。
一个很好的练习是打开一个交互式 python 控制台并输入“open”+ [ENTER]
>>> open
<built-in function open>
“open”不是上下文管理器对象,而是函数。它根本没有enter方法,而是通过以下方式定义的;
@contextmanager
def open(..):
...
..你可以用同样的方式定义你自己的上下文管理器函数,你甚至可以覆盖“open”的定义。
不过,IMO,如果您需要创建一个对象,然后将其用作带有参数的上下文管理器(..我所做的),最好的做法是为该对象提供一个方法,该方法返回一个定义输入方法的临时对象, 像这样;
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')
本例中调用链的顺序是;喜剧演员。init () -> Comedian.context(args) -> Roaster. 输入()
我觉得很多人都缺少这个答案,所以我添加了它。