Why does genexp(generator expression) is called genexp? not iterexp?

北城以北 提交于 2020-01-17 14:46:38

问题


A generator is a special kind of iterator, and it has some methods that an normal iterator doesn't have such as send(), close()... etc. One can get a generator by using a genexp like below:

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

the type of g will be a generator. But it seems weird to me that g is a generator because g.send will do nothing since g isn't returned by a function with yield keyword, and there would be no chance for one to catch the value passed by send method(not sure this is right), I don't see a reason that g needs to be a generator instead of a more generalize type:iterator.


回答1:


There seem to be some misunderstanding about definitions:

  1. Iterable is an object that implements __iter__. Also __iter__ is expected to return an iterator.
  2. Iterator is an object that implements next.
  3. Generator function is a function with yield keyword.
  4. Generator object is an object returned by a generator function. Every generator object is an iterator as well.
  5. Generator expression is a generator version of list comprehension. The result of generator expression is also called a generator object or simply a generator.

Some authors use general generator name in one of the meanings above. You have to know the context to truely understand what they are refering to. But since all those objects are closely tied there's no real problem with it.

It's always hard to answer questions "why is it like that?" when asking about naming conventions. Unless you ask the original creators its almost impossible to provide a satisfactory answer. For example it might simply be an effect of evolution and as we all know evolution does introduce errors. But here's my guess:

Both generator expressions and generator functions produce the same type of object. Now why do they produce the same object? That's probably because it was the easiest way to implement it like that under the hood. That might be the motivation.

Also note that there's a noticable difference between iterators and generator expressions: you can use yield keyword in generator expressions. Even though it is not really useful and introduces lots of confusion, the behaviour is not intuitive at all.

Resources:

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

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




回答2:


A lambda function is restricted in certain ways (no control structures, no doc string) but creates a real function object. You might ask in the same way, why does a lambda function have a __doc__ attribute that returns None, instead of AttributeError, since no lambda function could possibly have a doc string?

A subtype of a certain kind of value should be substitutable for values of the base type. (And special cases aren't special enough to break the rules.)

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

A generator expression looks like a list comprehension syntactically, but the value produced has the type generator iterator, and so should be usable in the same way as one produced using yield in a generator function. In this case, calling .send(foo) should do nothing except advance the function body.




回答3:


While genexps don't need and can't benefit from send functionality, they were introduced before send was a thing. Back then, generators had no additional API features over generic iterators.

Even if send had come first, it would probably have complicated the language more to document and implement another iterator type for genexps to evaluate to than to reuse the generator design.



来源:https://stackoverflow.com/questions/43943573/why-does-genexpgenerator-expression-is-called-genexp-not-iterexp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!