[英]Confused about “iterators” in python
I am studying python with the book Beginning Python: From Novice to Professional , and I get confused about the section discussing iterators
. 我正在使用Beginning Python:从新手到专业的书学习python,我对讨论iterators
的部分感到困惑。 There is an example in this section: 本节有一个例子:
>>> Class Fibs:
... def __init__(self):
... self.a = 0
... self.b = 1
... def __next__(self):
... self.a, self.b = self.b, self.a + self.b
... return self.a
... def __iter__(self):
... return self
...
>>> fibs = Fibs()
>>> for f in fibs:
... if f > 1000:
... print(f)
... break
...
1597
To be honest, I only know that fibs
is an object with methods __next__
and __iter__
, but have no idea about what happens in each step of the loop. 说实话,我只知道fibs
是一个方法__next__
和__iter__
的对象,但不知道循环的每一步发生了什么。 And I made a test: 我做了一个测试:
>>> isinstance(f, Fibs)
False
>>> f is fibs
False
>>> isinstance(f, int)
True
>>> fibs.a
1597
This makes me much more confused! 这让我更加困惑! Why the boolean value of f is fibs
is False
? 为什么f is fibs
的布尔值f is fibs
是False
? And why fibs.a
become 1597 after the execution of the loop?(Is the method __next__
automatically called in the loop?) Thanks in advance. 为什么在执行循环后fibs.a
变为1597?(方法__next__
是否在循环中自动调用?)提前感谢。
1 fibs = Fibs()
2 for f in fibs:
3 if f > 1000:
4 print(f)
5 break
Line 1 creates a Fibs() object, calling __init__()
. 第1行创建一个Fibs()对象,调用__init__()
。 Line 2 calls __iter__()
, which returns an iterator object (in this case, just fibs itself). 第2行调用__iter__()
,它返回一个迭代器对象(在本例中,只是fibs本身)。 The interpreter will then begin calling the __next__()
method repeatedly; 然后解释器将重复调用__next__()
方法; it returns self.a
, a plain number, which is assigned to the loop variable f
(so of course it's not a Fibs() object and certainly not the one named fibs). 它返回一个普通数字self.a
,它被分配给循环变量f
(当然它不是Fibs()对象,当然也不是名为fibs的那个)。 When that value reaches 1000, the if clause will fire, print the result, and break out of the loop. 当该值达到1000时,将触发if子句,打印结果并跳出循环。
And why fibs.a become 1597 after the execution of the loop? 为什么在执行循环后fibs.a变为1597?
Well this is because it is going through the Fibonacci sequence and this is the first number over 1000 in the sequence. 那么这是因为它正在经历Fibonacci序列 ,这是序列中第一个超过1000的数字。
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597 , 2584 ... 0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584 ...
On enter to the loop interpreter calls __iter__
method. 在输入循环解释器时调用__iter__
方法。 On every loop step interpreter calls __next__
method of Fibs
. 在每个循环步骤中,解释器调用Fibs
__next__
方法。
Yes, the loop automatically calls __next__
. 是的,循环自动调用__next__
。
The for
loop does this to the given object: for
循环对给定对象执行此操作:
# turn the object into an iterator
iterator = iter(given_object)
while True:
try:
# try to get the next value
next_value = next(iterator)
except StopIteration
# for loop is done, run the `else:` block if there is any
run_for_else_suite()
break
else:
# set the loop target to `next_value`
assign_next_value(next_value)
continue = run_loop_body()
if not continue:
break
The iter()
function calls given_object.__iter__()
, and the next()
function calls given_object.__next__()
; iter()
函数调用given_object.__iter__()
,而next()
函数调用given_object.__next__()
; these functions offer some extra functionality and are the proper way of calling into the iterator API. 这些函数提供了一些额外的功能,是调用迭代器API的正确方法。
So, in each loop iteration, f
is assigned the value that the Fib.__next__
method returned. 因此,在每次循环迭代中, f
被赋予Fib.__next__
方法返回的值。
You can also see that Fib
is its own iterator; 你还可以看到Fib
是它自己的迭代器; __iter__
returns self
. __iter__
返回self
。 Other types can return a dedicated iterator object; 其他类型可以返回专用的迭代器对象; lists do, for example: 列表做,例如:
>>> iter([])
<listiterator object at 0x129516610>
Returning dedicated iterators lets you create multiple 'views' on an object where each iterator maintains its own position, like nested loops: 返回专用迭代器允许您在对象上创建多个“视图”,其中每个迭代器都保持自己的位置,如嵌套循环:
lst = [1, 2, 3]
for i in lst:
for j in lst;
print (i, j) # prints (0, 0), (0, 1), (0, 2), (0, 3), (1, 0), etc.
or you can explicitly reuse the iterator: 或者您可以显式重用迭代器:
lst = [1, 2, 3]
lst_iter = iter(lst)
for i in lst_iter:
for j in lst_iter:
print (i, j) # prints (0, 1), (0, 2)
for f in fibs
implicitly calls fibs.__iter__
and binds f
to all the objects that it yields, in turn. 隐式调用fibs.__iter__
并fibs.__iter__
将f
绑定到它产生的所有对象。 None of these objects are instances of Fibs
, let alone equal to fibs
. 这些对象都不是Fibs
实例,更不用说等于fibs
。 The whole is (roughly) equivalent to 整体(大致)相当于
# boilerplate, implicit in the "for" notation
__iterator = iter(fibs)
while True:
try:
f = next(__iterator)
except StopIteration:
break
# your code, with f now bound to what the iterator yielded
if f > 1000:
print(f)
break
( iter
and next
are the clean ways to call __iter__
and __next__
, respectively.) ( iter
和next
分别是调用__iter__
和__next__
的简洁方法。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.