python - 输入 "with" 语句时 return 和 yield 的不同行为
问题描述
当我创建一个支持with
作用域的类时,当我在方法中使用 yield 和 return 作为最后一次调用时,我会得到不同且无法解释的行为__enter__
,代码:
class TestWith:
def __init__(self, val):
self.val=val
def __enter__(self):
print("Entered!")
yield
# return
def __exit__(self, exc_type, exc_val, exc_tb):
print(f"In exit:, type: {exc_type}, val: {exc_val}, tb: {exc_tb}")
with TestWith(4):
print("printme")
输出是:
printme
In exit:, type: None, val: None, tb: None
即“进入!” 不打印,更改__enter__
方法为:
def __enter__(self):
print("Entered!")
# yield
return
结果是:
Entered!
printme
In exit:, type: None, val: None, tb: None
为什么这两个实现有不同的行为?我也想像“进入!” 无论如何都会被打印,因为它是在 return/yield 之前调用的
解决方案
在函数定义中使用yield
使函数成为生成器,并且工作方式完全不同。这是一个例子:
>>> def func1():
... print('hi')
... yield
...
>>> def func2():
... print('hi')
... return
...
>>> func1() # returns a generator...doesn't execute the function!
<generator object func1 at 0x000002555B088510>
>>> func2()
hi
>>> g=func1() # save the generator
>>> next(g) # execute it to the next yield
hi
>>> next(g) # No more yields throws an exception
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
__enter__
意味着是一个正常的功能,而不是一个生成器,所以不要yield
在这种情况下使用。
推荐阅读
- php - 内网 PHP 页面上的文件 URL “不允许加载本地资源”
- s4sdk - CloudLoggerFactory 的 Sanitized Logger 在 Veracode Scan 中显示 CRLF 注入漏洞
- javascript - ReactJS - 如何从 json-server 迁移到 .json 文件?
- javascript - 循环遍历 json 对象并提取数据 - js
- android - Android Places API findCurrentPlace ApiException
- tfs - 在 TFS 2018 中积压转换后运行脚本
- css - lessc 的配置文件
- java - Java 库:Gate Creole ResourceInstantiationException
- javascript - 为什么我的 Shiny plot 下载应用无法在 IE 中运行?
- php - 使自定义字段出现在图像附件的标题中(Wordpress)