在 python 中,有没有一种方法可以检查函数是否是“生成器函数”?在调用之前?
假设我有两个函数:
def foo():
return 'foo'
def bar():
yield 'bar'
第一个是普通函数,第二个是生成器函数。现在我想写这样的内容:
def run(func):
if is_generator_function(func):
gen = func()
gen.next()
#... run the generator ...
else:
func()
is_generator_function()
的简单实现会是什么样子?使用 types
包我可以测试 gen
是否是生成器,但我希望在调用 func()
之前这样做。
现在考虑以下情况:
def goo():
if False:
yield
else:
return
调用 goo()
将返回一个生成器。我认为 python 解析器知道 goo() 函数有一个yield 语句,我想知道是否可以轻松获取该信息。
谢谢!
Lets say I have two functions:
def foo():
return 'foo'
def bar():
yield 'bar'
The first one is a normal function, and the second is a generator function. Now I want to write something like this:
def run(func):
if is_generator_function(func):
gen = func()
gen.next()
#... run the generator ...
else:
func()
What will a straightforward implementation of is_generator_function()
look like? Using the types
package I can test if gen
is a generator, but I wish to do so before invoking func()
.
Now consider the following case:
def goo():
if False:
yield
else:
return
An invocation of goo()
will return a generator. I presume that the python parser knows that the goo()
function has a yield statement, and I wonder if it possible to get that information easily.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如您所见,主要区别在于
bar
的字节码将至少包含一个YIELD_VALUE
操作码。我建议使用dis
模块(当然,将其输出重定向到 StringIO 实例并检查其getvalue
),因为这为您提供了对字节码更改的稳健性的衡量标准 -操作码的确切数值将会改变,但反汇编的符号值将保持相当稳定;-)。As you see, the key difference is that the bytecode for
bar
will contain at least oneYIELD_VALUE
opcode. I recommend using thedis
module (redirecting its output to a StringIO instance and checking itsgetvalue
, of course) because this provides you a measure of robustness over bytecode changes -- the exact numeric values of the opcodes will change, but the disassembled symbolic value will stay pretty stable;-).我已经实现了一个装饰器,它挂钩装饰函数返回/产生的值。它的基本原理是:
它之所以有效,是因为装饰器函数被无条件调用:它是被测试的返回值。
编辑:根据 Robert Lujo 的评论,我最终得到了类似的结果:
I've implemented a decorator that hooks on the decorated function returned/yielded value. Its basic goes:
It works because the decorator function is unconditionnaly called: it is the return value that is tested.
EDIT: Following the comment by Robert Lujo, I ended up with something like: