Python 将参数传递给u_enter__
只是通过陈述来学习 问题是,我可以把一个参数传递给Python 将参数传递给u_enter__,python,with-statement,Python,With Statement,只是通过陈述来学习 问题是,我可以把一个参数传递给\uuuuuu enter\uuuuu 我有这样的代码: class clippy_runner: def __enter__(self): self.engine = ExcelConnection(filename = "clippytest\Test.xlsx") self.db = SQLConnection(param_dict = DATASOURCES[STAGE_RELATIONAL])
\uuuuuu enter\uuuuu
我有这样的代码:
class clippy_runner:
def __enter__(self):
self.engine = ExcelConnection(filename = "clippytest\Test.xlsx")
self.db = SQLConnection(param_dict = DATASOURCES[STAGE_RELATIONAL])
self.engine.connect()
self.db.connect()
return self
我想将filename和param_dict作为参数传递给
\uuuu enter\uuuu
。那可能吗?不,你不能。将参数传递给\uuuu init\uuuu()
您是否可以通过类构造函数将值传递给
\uuuu init\uuu
#!/usr/bin/env python
class Clippy_Runner( dict ):
def __init__( self ):
pass
def __call__( self, **kwargs ):
self.update( kwargs )
return self
def __enter__( self ):
return self
def __exit__( self, exc_type, exc_val, exc_tb ):
self.clear()
clippy_runner = Clippy_Runner()
print clippy_runner.get('verbose') # Outputs None
with clippy_runner(verbose=True):
print clippy_runner.get('verbose') # Outputs True
print clippy_runner.get('verbose') # Outputs None
您可以使用contextmanager装饰器传递参数:
我觉得使用
contextmanager
可以提供参数,但不能将参数提供给\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>会让人感到困惑,我认为使用contextlib
更多详细信息,请参见下文
一个简单的例子
你的例子
输出
Carson
1
{'key': 'item_1'}
Carson: age=28
inside
__exit__
outside
ExcelConnection connect
SQLConnection connect
do something...
ExcelConnection disconnect
SQLConnection disconnect
关于contextmanager
上下文管理器(基本上)做三件事:
它在代码块之前运行一些代码
它在代码块之后运行一些代码
或者,它会抑制在代码块中引发的异常
被接受的答案(我觉得是不正确的)说你不能,你应该这样做
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()
..
…注意对象后面没有几个“()”,它是一个隐式函数调用,并且不接受任何参数
您可能会想到将参数传递给enterfrom
with open(filename) as file:
"do stuff with file..
但这与重写enter不同,因为“open”不是一个对象,而是一个函数
一个很好的练习是打开一个交互式python控制台并键入“open”+[ENTER]
>>> open
<built-in function open>
…您可以用同样的方法定义自己的上下文管理器功能,甚至可以覆盖“打开”的定义
但是,在我看来,如果您需要创建一个对象,然后将其用作带有参数的上下文管理器(…我所做的),那么最好的做法是为该对象提供一个方法,该方法返回一个临时对象,该对象定义了一个enter方法,如下所示
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()->喜剧演员。上下文(args)->烘焙者。输入()
我觉得这个答案在这一部分中不见了,所以我加了上去。我很困惑。因为您只是在\uuuu init\uuuu
中传递
,所以您是否建议在\uuuuu init\uuuu
函数中提供传递给的参数
<代码>定义初始化(self,filename,param_dict):self.filename=filename self.param_dict=param_dict
def\u输入(self):self.filename…
为什么这是公认的答案?我似乎不是唯一一个认为这是最糟糕的答案的人。“不,你不能,你把参数传递给init…”这根本不是真的,当然通过init传递参数是一种方法,但绝不是唯一的方法,也不总是最有意义的方法。。如果要将参数传递给位于的上下文管理器,请使用。。作为。。像OP这样的行,然后你肯定可以,这通常是最有意义的,取决于应用程序。(见所有其他答案)我支持这一点。我有一些只与上下文相关的设置。将它们传递给\uuuuu init\uuuuu
是愚蠢的。这似乎是my的正确答案,因为您不需要在with语句中创建变量,但可以使用一个容易创建的对象(如锁)并将变量传递给with语句。回答得好!回答得很好!这应该被接受,因为它可以在for
循环中使用,例如,无需每次迭代都实例化一个新对象
with object as alias:
alias.do_stuff()
..
with open(filename) as file:
"do stuff with file..
>>> open
<built-in function open>
@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')