装饰器是否可以将以下函数转换为生成器?使用装饰器将函数变成Python中的生成器
@decorator_that_makes_func_into_generator
def countdown(n):
while n > 0:
print n,
n = n - 1
该功能可以根据需要进行修改。请注意,该函数没有yield语句,否则它已经是一个生成器。
装饰器是否可以将以下函数转换为生成器?使用装饰器将函数变成Python中的生成器
@decorator_that_makes_func_into_generator
def countdown(n):
while n > 0:
print n,
n = n - 1
该功能可以根据需要进行修改。请注意,该函数没有yield语句,否则它已经是一个生成器。
如果你不能改变源的countdown
,你必须捕获输出:
import sys
from io import StringIO
def decorator_that_makes_func_into_generator(func):
def wrapper(*a, **ka):
# Temporarily redirect all output to StringIO instance (intr)
ts, intr = sys.stdout, StringIO()
sys.stdout = intr
func(*a, **ka)
# Restore normal stdout from backup (ts)
sys.stdout = ts
# Get output from intr, split it by whitespace and use it as generator
yield from intr.getvalue().split()
return wrapper
@decorator_that_makes_func_into_generator
def countdown(n):
while n > 0:
print(n)
n = n - 1
print(countdown(5), list(countdown(5)))
# <generator object wrapper at 0x01E09058> ['5', '4', '3', '2', '1']
如果你可以改变功能,如果你想从countdown
返回的东西(list
或其他序列类型)和然后创建从返回的对象的发电机,decorator'd像
def decorator_that_makes_func_into_generator(func):
def wrapper(*a, **ka):
yield from func(*a, **ka)
return wrapper
注:真棒yield from
是在Python 3.3引入的,在旧版本的使用,而不是简单的循环:
for x in func(*a, **ka):
yield x
例子:
@decorator_that_makes_func_into_generator
def countdown(n):
res = []
while n > 0:
res.append(n)
n = n - 1
return res
print(type(countdown(5)), list(countdown(5)))
# Output: <class 'generator'> [5, 4, 3, 2, 1]
没有什么阻止你将decorator_that_makes_func_into_generator
到发电机:
@decorator_that_makes_func_into_generator
def countdown(n):
while n > 0:
yield n
n = n - 1
print(type(countdown(5)), list(countdown(5)))
# Outputs <class 'generator'> [5, 4, 3, 2, 1]
不错!可能是因为他想要一个'return iter(func(* a,** ka))'对于包装函数来说足够了(它不会返回一个生成器,但也会被延迟)。 –
@frostnational,你能记录代码来解释装饰器函数中发生了什么吗?这将真正帮助 – user2979872
@ user2979872更新。 (我假设你知道装饰者是如何工作的) – vaultah
如果您无法更改该功能的主体,恐怕这太难了。
您试图包装的功能不是生成器,即使您将其包装到生成器中,该功能也会一次执行从头到尾执行。想必你不想那样。
理论上你能做什么?
print()
(更容易在Python3)
如果你真的疯了,你可以[在运行时修补字节码](http://www.jonathon-vogel.com/posts/patching_function_bytecode_with_python/) –