1

我正在通过《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__循环中自动调用?)提前谢谢。

4

5 回答 5

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

于 2013-10-10T13:36:33.523 回答
1

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

这是因为它正在通过斐波那契数列,这是该数列中第一个超过 1000 的数字。

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

于 2013-10-10T13:32:30.997 回答
0

进入循环解释器调用__iter__方法。在每个循环步骤解释器__next__调用Fibs.

于 2013-10-10T13:32:59.090 回答
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()函数调用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)
于 2013-10-10T13:33:00.807 回答
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

iter和分别是调用和next的简洁方式。)__iter____next__

于 2013-10-10T13:33:08.090 回答