为什么genexp(生成器表达式)被称为genexp?不是iterexp?

时间:2017-05-12 17:40:08

标签: python python-internals

生成器是一种特殊的迭代器,它有一些普通迭代器没有的方法,如 send() close() ..等等 可以通过使用如下的genexp获得生成器:

g=(i for i in range(3))

g的类型将是一个生成器。 但是对我来说, g 是一个生成器似乎很奇怪,因为 g.send 什么也不会做,因为g不是由 yield 的函数返回的关键字,并且没有机会捕获send方法传递的值(不确定这是对的),我没有看到 g 需要成为生成器而不是生成器的原因更通用的类型:迭代器。

3 个答案:

答案 0 :(得分:1)

似乎对定义存在一些误解:

  1. Iterable 是实现__iter__的对象。此外,__iter__还应返回迭代器。
  2. Iterator 是一个实现next
  3. 的对象
  4. 生成器功能是一个yield关键字的函数。
  5. 生成器对象是生成器函数返回的对象。每个生成器对象也是一个迭代器。
  6. 生成器表达式是列表推导的生成器版本。生成器表达式的结果也称为生成器对象或简称为生成器
  7. 有些作者使用上述其中一个含义中的通用生成器名称。你必须知道上下文才能真正理解他们所指的是什么。但由于所有这些对象都紧密相关,因此它并没有真正的问题。

    总是很难回答问题"为什么会这样?"在询问命名约定时。除非你问原创作者几乎不可能提供满意的答案。例如,它可能只是进化的影响,因为我们都知道进化确实会引入错误。但这是我的猜测:

    生成器表达式和生成器函数都生成相同类型的对象。现在为什么他们生产相同的物体?这可能是因为它是最简单的方式来实现它,就像在幕后。这可能是动机。

    另请注意,迭代器和生成器表达式之间存在显着差异:您可以在生成器表达式中使用yield关键字。尽管它并没有真正有用并且引入了许多混淆,但这种行为根本不是直观的。

    资源:

    https://wiki.python.org/moin/Iterator

    https://wiki.python.org/moin/Generators

答案 1 :(得分:0)

lambda函数以某种方式受到限制(没有控制结构,没有文档字符串),但会创建一个真正的函数对象。您可能会以同样的方式问,为什么lambda函数的__doc__属性返回None而不是AttributeError,因为没有lambda函数可能有文档字符串?

对于基本类型的值,某种值的子类型应为substitutable。 (特殊情况并不足以打破规则。)

>>> def g(): yield
>>> type(g())
<class 'generator'>
>>> h = (i for i in [1,2,3])
>>> type(h)
<class 'generator'>

生成器表达式在语法上看起来像列表解析,但生成的值具有类型生成器迭代器,因此应该可以使用与使用yield生成的值相同的方式使用发电机功能。在这种情况下,调用.send(foo)除了推进函数体之外什么都不做。

答案 2 :(得分:0)

虽然genexps不需要且无法从send功能中受益,但它们是在send之前引入的。那时,生成器没有通用迭代器的额外API功能。

即使send首先出现,也可能会使语言更复杂,以便为genxps记录和实现另一个迭代器类型来评估,而不是重用发生器设计。