gpt4 book ai didi

python - 退出 python 上下文管理器时返回值

转载 作者:太空狗 更新时间:2023-10-29 21:41:21 25 4
gpt4 key购买 nike

也许这是一个愚蠢的(而且确实不是很实用的)问题,但我问这个问题是因为我无法理解它。

在研究调用上下文管理器中的 return 语句是否会阻止调用 __exit__ 时(不,不会),我发现这似乎很常见在 try/finally block 中对 __exit__finally 进行类比(例如此处:https://stackoverflow.com/a/9885287/3471881),因为:

def test():
try:
return True
finally:
print("Good bye")

将执行相同的:

class MyContextManager:

def __enter__(self):
return self

def __exit__(self, *args):
print('Good bye')

def test():
with MyContextManager():
return True

这确实帮助我理解了 cm:s 是如何工作的,但在玩了一会儿之后我意识到,如果我们返回某些东西而不是打印,这个类比就不会起作用。

def test():
try:
return True
finally:
return False
test()
--> False

虽然 __exit__ 似乎根本不会返回:

class MyContextManager:

def __enter__(self):
return self

def __exit__(self, *args):
return False

def test():
with MyContextManager():
return True

test()
--> True

这让我想到也许您实际上无法在 __exit__ 中返回任何内容,但您可以:

class MyContextManager:

def __enter__(self):
return self

def __exit__(self, *args):
return self.last_goodbye()

def last_goodbye(self):
print('Good bye')

def test():
with MyContextManager():
return True
test()
--> Good bye
--> True

请注意,如果我们不在 test() 函数中返回任何内容,这并不重要。

这引出了我的问题:

  • 是否不可能从 __exit__ 内部返回一个值?如果是,为什么?

最佳答案

是的。从 __exit__ 内部改变上下文的返回值是不可能的。

如果使用 return 语句退出上下文,则不能使用 context_manager.__exit__ 更改返回值。这与 try ... finally ... 子句不同,因为 finally 中的代码仍然属于父函数,而 context_manager.__exit__ 在其自己的范围内运行.

事实上,__exit__ 可以返回一个 bool 值(TrueFalse),它会被 Python 理解。它告诉 Python 是否应该抑制退出上下文的异常(如果有)(不传播到上下文之外)。

__exit__的返回值的含义见这个例子:

>>> class MyContextManager:
... def __init__(self, suppress):
... self.suppress = suppress
...
... def __enter__(self):
... return self
...
... def __exit__(self, exc_type, exc_obj, exc_tb):
... return self.suppress
...
>>> with MyContextManager(True): # suppress exception
... raise ValueError
...
>>> with MyContextManager(False): # let exception pass through
... raise ValueError
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError
>>>

在上面的例子中,两个ValueError都会导致控件跳出上下文。在第一个 block 中,上下文管理器的 __exit__ 方法返回 True,因此 Python 抑制了这个异常,它不会在 REPL 中反射。在第二个 block 中,上下文管理器返回 False,因此 Python 让外部代码处理异常,该异常由 REPL 打印出来。

关于python - 退出 python 上下文管理器时返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54076972/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com