我正在尝试实现我自己的itertools.compress
版本,问题是我偶然发现了返回类型。我的意思是这两个函数都返回一个迭代器,但我认为第二个函数不被认为是生成器函数,因为里面没有yield语句。所以我的问题是,这两个实现是否相同?
def compress (seq, selectors):
from operator import itemgetter
fst = itemgetter (0)
snd = itemgetter (1)
yield from map (fst, filter (snd, zip (seq, selectors)))
def compress (seq, selectors):
from operator import itemgetter
fst = itemgetter (0)
snd = itemgetter (1)
return map (fst, filter (snd, zip (seq, selectors)))
答案 0 :(得分:4)
不完全。
yield from seq
相当于for i in seq: yield i
这意味着你的第一个实现是一个生成器,它从map()的结果中产生每个项目,而你的第二个实现返回map对象。
答案 1 :(得分:3)
虽然它们可能看起来非常相似,甚至输出结果,但它们并不相同。
查看这些基本代码示例,将str
映射到range(100)
def do_yield_from():
yield from map(str, range(100))
def do_return():
return map(str, range(100))
print(do_yield_from())
print(do_return())
>>> <class 'generator'>
>>> <class 'map'>
第一个函数是generator
,产生do_yield_from
的结果和
for r in range(100): yield str(r)
第二个函数返回map
的实例,该实例是iterator
而不是generator
。
由于第一项功能是generator
,yield from
的效果优于do_return
import timeit
print(timeit.timeit(do_yield_from))
>>> 0.53931242968009
print(timeit.timeit(do_return))
>>> 1.467075402143485
答案 2 :(得分:2)
所以我的问题是,这两个实现是否相同?
完全没有。
yield from
和return
是两种不同的,独特的句法结构。
yield from
是PEP380中引入的语法。它被称为生成器委派。 From the documentation:
然而,PEP 380添加
yield from
表达式,允许生成器将其部分操作委托给另一个生成器。这允许将包含yield的一段代码分解出来并放在另一个生成器中。此外,允许子生成器返回一个值,该值可供委派生成器使用。
return
具有完全不同的行为。 From the documentation:
return只能在语法上嵌套在函数定义中,而不能嵌套在类定义中。
如果存在表达式列表,则对其进行评估,否则替换为无。
return将当前函数调用与表达式列表(或
None
)一起作为返回值。
基本上yield from <iter>
与for element in <iter>: yield element
相当,而return
只会返回一个值。
在您的情况下,我相信yield from
是您正在寻找的。您希望yield
来自map
迭代器的值,而不是return
迭代器本身。