問題描述
我正在閱讀有關(guān)生成器和迭代器以及 __next__()
的作用的信息.
I was reading about generator and iterators and the role of __next__()
.
'__next__' in dir(mygen)
.是真的
'__next__' in dir(mylist)
,為假
當(dāng)我深入研究它時,
'__next__' in dir (mylist.__iter__())
為真
為什么
__next__
僅可用于列出,而僅可用于__iter__()
和mygen
而不能用于mylist代碼>.
__iter__()
當(dāng)我們使用 list-comprehension 遍歷列表時如何調(diào)用__next__
why is
__next__
only available to list but only to__iter__()
andmygen
but notmylist
. How does__iter__()
call__next__
when we are stepping thru the list using list-comprehension
嘗試手動升級生成器 (+1),我調(diào)用了 mygen.__next__()
.它不存在.它僅作為 mygen.__next__
存在,稱為 method-wrapper.
Trying to manually step (+1) up the generator, I called mygen.__next__()
. It doesn't exist. It only exist as mygen.__next__
which is called method-wrapper.
什么是方法包裝器,它有什么作用?它在這里是如何應(yīng)用的:在 mygen() 和 __iter__() 中?
what is a method-wrapper and what does it do? How is it applied here: in mygen() and __iter__() ?
如果 __next__
是生成器和迭代器都提供的(以及它們唯一的屬性),那么生成器和迭代器有什么區(qū)別?*
if __next__
is what both generator and iterator provide (and their sole properties) then what is the difference between generator and iterator?*
答案 3:已解決,如 mod/editor 所述:
Answer to 3: Solved, as noted by mod/editor:
Python 的生成器和迭代器的區(qū)別
更新:生成器和迭代器都有 __next__()
.我的錯.查看日志,不知何故 mygen.__next__()
測試給了我停止迭代異常錯誤.但我無法再次復(fù)制該錯誤.
UPDATE: both generator and iterator have __next__()
. My mistake. Looking at the logs, somehow mygen.__next__()
test was giving me stopiteration exception error. But I wasn't able to duplicate that error again.
感謝大家的回答!
推薦答案
特殊方法 __iter__
和 __next__
是迭代器協(xié)議的一部分,用于創(chuàng)建 迭代器類型.為此,您必須區(qū)分兩個不同的事物:Iterables 和 iterators.
The special methods __iter__
and __next__
are part of the iterator protocol to create iterator types. For this purpose, you have to differentiate between two separate things: Iterables and iterators.
Iterables 是可以迭代的東西,通常,這些是包含項目的某種容器元素.常見的例子是列表、元組或字典.
Iterables are things that can be iterated, usually, these are some kind of container elements that contain items. Common examples are lists, tuples, or dictionaries.
為了迭代一個可迭代對象,你使用一個迭代器.迭代器是幫助您遍歷容器的對象.例如,在迭代列表時,迭代器本質(zhì)上會跟蹤您當(dāng)前所在的索引.
In order to iterate an iterable, you use an iterator. An iterator is the object that helps you iterate through the container. For example, when iterating a list, the iterator essentially keeps track of which index you are currently at.
為了獲得一個迭代器,__iter__
方法在迭代器上被調(diào)用.這就像一個工廠方法,它為這個特定的迭代返回一個新的迭代器.定義了 __iter__
方法的類型,將其轉(zhuǎn)換為可迭代對象.
To get an iterator, the __iter__
method is called on the iterable. This is like a factory method that returns a new iterator for this specific iterable. A type having a __iter__
method defined, turns it into an iterable.
迭代器通常需要一個方法,__next__
,它返回迭代的next項.此外,為了使協(xié)議更易于使用,每個迭代器也應(yīng)該是一個可迭代的,在 __iter__
方法中返回自己.
The iterator generally needs a single method, __next__
, which returns the next item for the iteration. In addition, to make the protocol easier to use, every iterator should also be an iterable, returning itself in the __iter__
method.
舉個簡單的例子,這可能是一個列表的迭代器實現(xiàn):
As a quick example, this would be a possible iterator implementation for a list:
class ListIterator:
def __init__ (self, lst):
self.lst = lst
self.idx = 0
def __iter__ (self):
return self
def __next__ (self):
try:
item = self.lst[self.idx]
except IndexError:
raise StopIteration()
self.idx += 1
return item
然后列表實現(xiàn)可以簡單地從 __iter__
方法返回 ListIterator(self)
.當(dāng)然,列表的實際實現(xiàn)是在 C 中完成的,所以這看起來有點不同.但想法是一樣的.
The list implementation could then simply return ListIterator(self)
from the __iter__
method. Of course, the actual implementation for lists is done in C, so this looks a bit different. But the idea is the same.
迭代器在 Python 的各個地方都以不可見的方式使用.例如 for
循環(huán):
Iterators are used invisibly in various places in Python. For example a for
loop:
for item in lst:
print(item)
這與以下內(nèi)容類似:
lst_iterator = iter(lst) # this just calls `lst.__iter__()`
while True:
try:
item = next(lst_iterator) # lst_iterator.__next__()
except StopIteration:
break
else:
print(item)
所以 for 循環(huán)從可迭代對象請求一個迭代器,然后在該可迭代對象上調(diào)用 __next__
直到它遇到 StopIteration
異常.這發(fā)生在表面之下也是您希望迭代器也實現(xiàn) __iter__
的原因:否則您永遠無法循環(huán)遍歷迭代器.
So the for loop requests an iterator from the iterable object, and then calls __next__
on that iterable until it hits the StopIteration
exception. That this happens under the surface is also the reason why you would want iterators to implement the __iter__
as well: Otherwise you could never loop over an iterator.
對于生成器,人們通常所說的實際上是生成器function,即一些具有yield
語句的函數(shù)定義.一旦你調(diào)用了那個生成器函數(shù),你就會得到一個generator.生成器本質(zhì)上只是一個迭代器,盡管它是一個花哨的迭代器(因為它不僅僅是在容器中移動).作為一個迭代器,它有一個 __next__
方法來生成"下一個元素,以及一個 __iter__
方法來返回自己.
As for generators, what people usually refer to is actually a generator function, i.e. some function definition that has yield
statements. Once you call that generator function, you get back a generator. A generator is esentially just an iterator, albeit a fancy one (since it does more than move through a container). As an iterator, it has a __next__
method to "generate" the next element, and a __iter__
method to return itself.
一個示例生成器函數(shù)如下:
An example generator function would be the following:
def exampleGenerator():
yield 1
print('After 1')
yield 2
print('After 2')
包含 yield
語句的函數(shù)體將其轉(zhuǎn)換為生成器函數(shù).這意味著當(dāng)你調(diào)用 exampleGenerator()
時,你會得到一個 generator 對象.生成器對象實現(xiàn)了迭代器協(xié)議,因此我們可以在其上調(diào)用 __next__
(或使用上面的 next()
函數(shù)):
The function body containing a yield
statement turns this into a generator function. That means that when you call exampleGenerator()
you get back a generator object. Generator objects implement the iterator protocol, so we can call __next__
on it (or use the the next()
function as above):
>>> x = exampleGenerator()
>>> next(x)
1
>>> next(x)
After 1
2
>>> next(x)
After 2
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
next(x)
StopIteration
請注意,第一個 next()
調(diào)用尚未打印任何內(nèi)容.這是生成器的特殊之處:它們是惰性的,并且只評估從可迭代項中獲取下一項所需的值.只有通過第二次 next()
調(diào)用,我們才能從函數(shù)體中獲得第一行打印.我們需要另一個 next()
調(diào)用來耗盡可迭代對象(因為沒有產(chǎn)生另一個值).
Note that the first next()
call did not print anything yet. This is the special thing about generators: They are lazy and only evaluate as much as necessary to get the next item from the iterable. Only with the second next()
call, we get the first printed line from the function body. And we need another next()
call to exhaust the iterable (since there’s not another value yielded).
但除了那種懶惰之外,生成器就像迭代一樣.你甚至?xí)谧詈蟮玫揭粋€ StopIteration
異常,它允許生成器(和生成器函數(shù))用作 for
循環(huán)源以及可以使用正常"迭代的任何地方.
But apart from that laziness, generators just act like iterables. You even get a StopIteration
exception at the end, which allows generators (and generator functions) to be used as for
loop sources and wherever "normal" iterables can be used.
生成器及其惰性的最大好處是能夠按需生成東西.一個很好的類比是網(wǎng)站上的無休止?jié)L動:您可以在之后(在生成器上調(diào)用 next()
)之后向下滾動項目,并且每隔一段時間,網(wǎng)站將不得不查詢后端檢索更多項目供您滾動瀏覽.理想情況下,這種情況會在您不注意的情況下發(fā)生.這正是生成器所做的.它甚至允許這樣的事情:
The big benefit of generators and their laziness is the ability to generate stuff on demand. A nice analogy for this is endless scrolling on websites: You can scroll down item after after (calling next()
on the generator), and every once in a while, the website will have to query a backend to retrieve more items for you to scroll through. Ideally, this happens without you noticing. And that’s exactly what a generator does. It even allows for things like this:
def counter():
x = 0
while True:
x += 1
yield x
非懶惰,這是不可能計算的,因為這是一個無限循環(huán).但是懶惰的是,作為一個生成器,它可以在一個項目之后消費這個迭代的一個項目.我原本想讓你不用將這個生成器實現(xiàn)為完全自定義的迭代器類型,但在這種情況下,這實際上并不太難,所以就這樣吧:
Non-lazy, this would be impossible to compute since this is an infinite loop. But lazily, as a generator, it’s possible to consume this iterative one item after an item. I originally wanted to spare you from implementing this generator as a fully custom iterator type, but in this case, this actually isn’t too difficult, so here it goes:
class CounterGenerator:
def __init__ (self):
self.x = 0
def __iter__ (self):
return self
def __next__ (self):
self.x += 1
return self.x
這篇關(guān)于__next__ 在生成器和迭代器中,什么是方法包裝器?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!