对python中的“迭代器”感到困惑

时间:2013-10-10 13:25:35

标签: python

我正在使用书籍Beginning Python: From Novice to Professional学习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的布尔值为False?为什么fibs.a在执行循环后变为1597?(方法__next__是否在循环中自动调用?)提前感谢。

5 个答案:

答案 0 :(得分:3)

 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子句,打印结果并跳出循环。

答案 1 :(得分:1)

  

为什么在执行循环后fibs.a变为1597?

这是因为它正在通过Fibonacci sequence,这是序列中第一个超过1000的数字。

  

0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,    1597 ,2584 ......

答案 2 :(得分:0)

输入循环解释器调用__iter__方法。在每个循环步骤中,解释器调用__next__的{​​{1}}方法。

答案 3 :(得分:0)

是的,循环会自动调用__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() function来电given_object.__iter__()next() function来电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)

答案 4 :(得分:0)

for f in fibs

隐式调用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

iternext分别是__iter____next__的简洁方式。)