А几个小时前,我提交了related question,并得到了答案,为什么我需要向装饰器中添加yield
才能正常工作。
我最近回想起我由于某种原因而忽略了它-一种我无法解释的奇怪行为。
如果我是盲人,我会提前道歉,但是我花了几个小时盯着这个代码玩,这就是我得到的:
def decor(func):
def wrapper(*args, **kwargs):
if 1==2:
print ("Generator")
for item in func(*args, **kwargs):
print(item)
#yield(item)
else:
print ("Not generator")
res = func(*args, **kwargs)
print(res)
return res
return wrapper
@decor
def f():
return "a"
f()
"""
Output:
Not generator
a
"""
如果我在yield
之前删除评论,则根本没有输出。
那是为什么?我在if 1==2:
语句中所做的任何更改怎么可能对脚本产生影响?
答案 0 :(得分:4)
如果函数的主体中任何地方包含yield
,则该函数为生成器函数。是否执行yield
并不重要。 1 == 2
为假的事实与它无关。
考虑以下功能:
def addone(numbers):
for number in numbers:
yield number + 1
致电addone([])
会发生什么? yield
从未执行,但是addone
仍返回生成器。为什么这应该有所不同:
def addone(numbers):
if numbers:
for number in numbers:
yield number + 1
因此很明显,实际上是否执行yield
无关紧要。唯一相关的事实是yield
是否存在于函数主体中。
修复相对简单,您所要做的就是将带有yield
的部分拉到一个单独的函数中:
import types
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
if isinstance(result, types.GeneratorType):
print("Is a generator")
return wrap_generator(result)
print("Not a generator")
return result
def wrap_generator(gen):
for item in gen:
print(item)
yield item
通常,这里的问题是函数是生成器(使用yield
)还是普通函数(使用return
)。当您在同一函数中同时使用yield
和return
时,会有些混乱!
对于Python,事实证明,如果在同一函数中同时使用yield
和return
,则该函数是一个生成器函数。这可能有些令人困惑,因此从样式上来说,我通常会避免在同一函数中同时使用return
和yield
。