[英]Confused about “iterators” in python
我正在使用Beginning Python:从新手到专业的书学习python,我对讨论iterators
的部分感到困惑。 本节有一个例子:
>>> 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
说实话,我只知道fibs
是一个方法__next__
和__iter__
的对象,但不知道循环的每一步发生了什么。 我做了一个测试:
>>> isinstance(f, Fibs)
False
>>> f is fibs
False
>>> isinstance(f, int)
True
>>> fibs.a
1597
这让我更加困惑! 为什么f is fibs
的布尔值f is fibs
是False
? 为什么在执行循环后fibs.a
变为1597?(方法__next__
是否在循环中自动调用?)提前感谢。
1 fibs = Fibs()
2 for f in fibs:
3 if f > 1000:
4 print(f)
5 break
第1行创建一个Fibs()对象,调用__init__()
。 第2行调用__iter__()
,它返回一个迭代器对象(在本例中,只是fibs本身)。 然后解释器将重复调用__next__()
方法; 它返回一个普通数字self.a
,它被分配给循环变量f
(当然它不是Fibs()对象,当然也不是名为fibs的那个)。 当该值达到1000时,将触发if子句,打印结果并跳出循环。
为什么在执行循环后fibs.a变为1597?
那么这是因为它正在经历Fibonacci序列 ,这是序列中第一个超过1000的数字。
0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584 ...
在输入循环解释器时调用__iter__
方法。 在每个循环步骤中,解释器调用Fibs
__next__
方法。
是的,循环自动调用__next__
。
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
iter()
函数调用given_object.__iter__()
,而next()
函数调用given_object.__next__()
; 这些函数提供了一些额外的功能,是调用迭代器API的正确方法。
因此,在每次循环迭代中, f
被赋予Fib.__next__
方法返回的值。
你还可以看到Fib
是它自己的迭代器; __iter__
返回self
。 其他类型可以返回专用的迭代器对象; 列表做,例如:
>>> iter([])
<listiterator object at 0x129516610>
返回专用迭代器允许您在对象上创建多个“视图”,其中每个迭代器都保持自己的位置,如嵌套循环:
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.
或者您可以显式重用迭代器:
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
隐式调用fibs.__iter__
并fibs.__iter__
将f
绑定到它产生的所有对象。 这些对象都不是Fibs
实例,更不用说等于fibs
。 整体(大致)相当于
# 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
和next
分别是调用__iter__
和__next__
的简洁方法。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.