Car*_*los 57 python function generator coroutine
可以说我有两个功能:
def foo():
return 'foo'
def bar():
yield 'bar'
Run Code Online (Sandbox Code Playgroud)
第一个是正常函数,第二个是生成器函数.现在我想写这样的东西:
def run(func):
if is_generator_function(func):
gen = func()
gen.next()
#... run the generator ...
else:
func()
Run Code Online (Sandbox Code Playgroud)
什么是直截了当的实现is_generator_function()
?使用types
包我可以测试是否 gen
是生成器,但我希望在调用之前这样做func()
.
现在考虑以下情况:
def goo():
if False:
yield
else:
return
Run Code Online (Sandbox Code Playgroud)
调用goo()
将返回生成器.我假设python解析器知道该goo()
函数有一个yield语句,我想知道是否可以轻松获取该信息.
谢谢!
Cor*_*erg 65
>>> import inspect
>>>
>>> def foo():
... return 'foo'
...
>>> def bar():
... yield 'bar'
...
>>> print inspect.isgeneratorfunction(foo)
False
>>> print inspect.isgeneratorfunction(bar)
True
Run Code Online (Sandbox Code Playgroud)
Gre*_*ill 15
实际上,我想知道这样一个假设是多么有用is_generator_function()
.考虑:
def foo():
return 'foo'
def bar():
yield 'bar'
def baz():
return bar()
def quux(b):
if b:
return foo()
else:
return bar()
Run Code Online (Sandbox Code Playgroud)
我应该is_generator_function()
返回baz
和quux
?baz()
返回一个生成器但不是一个生成器,quux()
可能会返回一个生成器,也可能不返回.
>>> def foo():
... return 'foo'
...
>>> def bar():
... yield 'bar'
...
>>> import dis
>>> dis.dis(foo)
2 0 LOAD_CONST 1 ('foo')
3 RETURN_VALUE
>>> dis.dis(bar)
2 0 LOAD_CONST 1 ('bar')
3 YIELD_VALUE
4 POP_TOP
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
>>>
Run Code Online (Sandbox Code Playgroud)
如您所见,关键区别在于字节码bar
将包含至少一个YIELD_VALUE
操作码.我建议使用该dis
模块(当然,将其输出重定向到StringIO实例并检查它getvalue
),因为这为您提供了字节码更改的稳健性测量 - 操作码的确切数值将会改变,但反汇编的符号值将保持不变相当稳定;-).