iter()内置的重点是什么?

时间:2014-02-23 15:23:10

标签: python

使用iter(),我可以这样做:

>>> listWalker = iter ( [23, 47, 'hike'] )
>>> for x in listWalker: print x,

但我还是可以这样做:

>>> listWalker = [23, 47, 'hike']
>>> for x in listWalker: print x,

它增加了什么价值?

4 个答案:

答案 0 :(得分:5)

除了使用iter显式获取实现__iter__方法的对象的迭代器之外,还有一个鲜为人知的双参数形式iter,这使得重复调用函数的迭代器,直到它返回给定的sentinel值。

 for line in iter(f.readline, 'EOF'):
     print line

前面的代码会调用f.read(例如,打开文件句柄f),直到它读取由字符串EOF组成的行。它与写作大致相同

for line in f:
    if line == "EOF":
        break
    print line

此外,迭代器可能是与迭代的对象不同的对象。这适用于list类型。这意味着您可以创建两个迭代器,这两个迭代器都在同一个对象上独立地迭代

itr1 = iter(mylist)
itr2 = iter(mylist)

x = next(itr1)   # First item of mylist
y = next(itr1)   # Second item of my list
z = next(itr2)   # First item of mylist, not the third

然而,文件句柄充当它们自己的迭代器:

>>> f = open('.bashrc')
>>> id(f)
4454569712
>>> id(iter(f))
4454569712

通常,iter返回的对象取决于对象类型实现的__iter__方法。

答案 1 :(得分:4)

iter的要点是它允许你从一个可迭代的对象中获取迭代器并自己使用它,要么实现你自己的for循环变体,要么保持状态为跨多个循环的迭代。一个简单的例子:

it = iter(['HEADER', 0, 1, 2, 3])  # coming from CSV or such
title = it.next()
for item in it:
    # process item
    ...

此分组习惯用法提供了iter的更高级用法:

def in_groups(iterable, n):
    """Yield element from iterables grouped in tuples of size n."""
    it = iter(iterable)
    iters = [it] * n
    return zip(*iters)

答案 2 :(得分:0)

当您对变量执行for循环时,它会隐式调用您实际传递的迭代的__iter__方法。
当你循环遍历列表,元组和每个可迭代时,你总是使用iter()

我认为这个字节码的提取可以说服你:

>>> def a():
...     for x in [1,2,3]:
...         print x
...
>>> import dis
>>> dis.dis(a)
  2           0 SETUP_LOOP              28 (to 31)
              3 LOAD_CONST               1 (1)
              6 LOAD_CONST               2 (2)
              9 LOAD_CONST               3 (3)
             12 BUILD_LIST               3
             15 GET_ITER                                 # <--- get iter is important here
        >>   16 FOR_ITER                11 (to 30)
             19 STORE_FAST               0 (x)

  3          22 LOAD_FAST                0 (x)
             25 PRINT_ITEM
             26 PRINT_NEWLINE
             27 JUMP_ABSOLUTE           16
        >>   30 POP_BLOCK
        >>   31 LOAD_CONST               0 (None)
             34 RETURN_VALUE

<小时/> 但是,iterables还允许您在Py​​thon中使用其他一些东西,例如使用next()来进入迭代,或者提升StopIteration exception。如果您正在处理不同的对象类型并且想要应用通用算法,那么它将非常有用。

答案 3 :(得分:0)

来自the docs

  

iter(o [,sentinel])

     

[...]没有第二个参数,o必须是一个支持。的集合对象   迭代协议(__iter__()方法),或者它必须支持   序列协议(带有整数参数的__getitem__()方法   从0开始)。如果它不支持这些协议中的任何一个,   引发TypeError。 [...]

所以它从一个对象构造一个迭代器。

正如你所说,这是在循环和理解中自动完成的,但有时候你想得到一个迭代器并直接处理它。只要你需要它就可以把它放在心里。

使用第二个参数时:

  

如果给出第二个参数 sentinel ,则o必须是可调用对象。   在这种情况下创建的迭代器将调用o,每次调用都没有参数   到它的next()方法;如果返回的值等于sentinel,   将引发StopIteration,否则将返回该值。

这对许多事情都很有用,但对于像file.read(bufsize)这样的遗留风格函数尤其如此,在返回""之前必须重复调用它。可以使用iter(lambda : file.read(bufsize), "")将其转换为迭代器。很干净!