简体   繁体   English

有没有办法区分这个迭代器和这个生成器?

[英]Is there a way to distinguish this iterator from this generator?

I am aware of this question:我知道这个问题:

Difference between Python's Generators and Iterators Python 的生成器和迭代器的区别

It is more broadly and less technically based.它的范围更广,技术基础更少。 And none of the answers have been selected.而且没有一个答案被选中。 I also read through those answers and with one possible exception did not find what I was looking for.我还通读了这些答案,除了一个可能的例外,没有找到我想要的东西。 I wish to ask a more precise question to help me understand some details.我想问一个更准确的问题来帮助我理解一些细节。

I asked this question earlier:我之前问过这个问题:

What is the difference between a python itterator and a python generator? python 迭代器和 python 生成器有什么区别?

Perhaps the title or the way I asked the question was misleading, since the response I did get was not on target to my intentions and the question was closed within seconds.也许标题或我提出问题的方式具有误导性,因为我得到的回答并不符合我的意图,而且问题在几秒钟内就结束了。

So I will try to clarify here.所以我会试着在这里澄清一下。

Consider the following code:考虑以下代码:

p = [k for k in range(1,1000)]
i = iter(p)
g = (k for k in p)

Is there some operation that can be done on i and g that will distinguish between these two constructions.是否可以对 i 和 g 进行一些操作来区分这两种结构。 Something that I can do with i that I can't do with g, that sort of thing.我可以用 i 做而我不能用 g 做的事情,诸如此类。 Their type comes out as list iterator versus generator object, but it is unclear to me that this has any pragmatic impact on what one can do with it, or its efficiency.它们的类型以列表迭代器与生成器 object 的形式出现,但我不清楚这对人们可以用它做什么或它的效率有任何实际影响。 I deliberately have constructed the list first to emphasize that the issue of generating the list up front or on demand is not what the question is about.我特意首先构建了列表,以强调预先或按需生成列表的问题不是问题所在。

At the moment, I suspect that the answer to the more general question is this - generators are a special case of iterators and whatever you can do with generator construction using either comprehensions or yield can be done by explicitly writing the corresponding iterator.目前,我怀疑更普遍的问题的答案是这样的——生成器是迭代器的一个特例,无论你可以使用推导式或产量来构造生成器,都可以通过显式编写相应的迭代器来完成。 The justification for using a generator rather than an iterator is that sometimes it is easier to write.使用生成器而不是迭代器的理由是有时它更容易编写。


Later I found this question that lead to some good exposition on the topic.后来我发现这个问题导致了对该主题的一些很好的阐述。

How to write a generator class? 如何编写生成器 class?

g supports send , as all generators do, while i doesn't. g支持send ,就像所有生成器一样,而i不支持。 ( send ing to g isn't useful , but you can do it.) sendg没有,但你可以做到。)

>>> g.send(None)
1
>>> i.send(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list_iterator' object has no attribute 'send'

You can also throw exceptions into g or close it, which you can't do with i .您还可以将异常throwg中或将其close ,这是i无法做到的。

i can be pickled, while g can't. i可以腌制,而g不能。

Aside from that, you can do all sorts of explicit checks and introspection to distinguish them.除此之外,您可以进行各种显式检查和自省来区分它们。 Checking the types, examining the str output, looking for attributes that only exist on one or the other (like g.gi_frame ), etc.检查类型,检查str output,寻找只存在于一个或另一个上的属性(如g.gi_frame )等。

Most of this is implementation details or incidental, not something you should think of as "the difference between generators and iterators".其中大部分是实现细节或附带的,而不是您应该将其视为“生成器和迭代器之间的区别”。 Generators are a kind of iterator.生成器是一种迭代器。

Here are some excerpts from the documentation:以下是文档的一些摘录:

4.5.1 Generator type: 4.5.1 发电机类型:
Python's generators provide a convenient way to implement the iterator protocol. Python 的生成器提供了一种方便的方式来实现迭代器协议。

and later:然后:

6.2.9. 6.2.9。 Yield expressions:产量表达式:
When a generator function is called, it returns an iterator known as a generator.当调用生成器 function 时,它返回一个称为生成器的迭代器。

=> a generator function creates an iterator => 一个生成器 function 创建一个迭代器

The next paragraphs gives the additional methods of a generator:接下来的段落给出了生成器的其他方法:

6.2.9.1. 6.2.9.1。 Generator-iterator methods生成器迭代器方法
This subsection describes the methods of a generator iterator.本小节描述生成器迭代器的方法。

generator.__next__() : ... generator.__next__() : ...

same behaviour as iterator.next()iterator.next()相同的行为

generator.send(value)
Resumes the execution and “sends” a value into the generator function...恢复执行并将值“发送”到生成器 function...

`generator.throw(type[, value[, traceback]])`` `generator.throw(type[, value[, traceback]])`
Raises an exception of type type at the point where the generator was paused, and returns the next value yielded by the generator function...在生成器暂停时引发类型类型异常,并返回生成器 function 生成的下一个值...

generator.close()
Raises a GeneratorExit at the point where the generator function was paused...在生成器 function 暂停的位置引发 GeneratorExit...

That means that a generator is a special case of an iterator with some additional methods.这意味着生成器是具有一些附加方法的迭代器的特例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM