`return iterator`和`from iterator`之间的区别

时间:2017-08-10 18:01:52

标签: python python-3.x itertools yield-from

我正在尝试实现我自己的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)))

3 个答案:

答案 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

由于第一项功能是generatoryield from的效果优于do_return

import timeit
print(timeit.timeit(do_yield_from))
>>> 0.53931242968009

print(timeit.timeit(do_return))
>>> 1.467075402143485

答案 2 :(得分:2)

  

所以我的问题是,这两个实现是否相同?

完全没有。

yield fromreturn是两种不同的,独特的句法结构。

yield fromPEP380中引入的语法。它被称为生成器委派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迭代器本身。