iter()内置函数的作用是什么?

3

使用iter(),我可以做到这一点:

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

但我仍然可以做到这一点:
>>> listWalker = [23, 47, 'hike']
>>> for x in listWalker: print x,

它能增加哪些价值?


这里有一个很好的使用 iter 的示例:链接 - GWW
@CharlesDuffy 这不是重复的问题。链接的问题问为什么 iter(some_iterator) 起作用。而这个问题问的是为什么存在一个 iter 函数(当 for 本来就能完成任务时)。这两个问题并不相同。 - user4815162342
@user4815162342,问题确实不一样,但答案完全适用。 - Charles Duffy
@CharlesDuffy 接受/得票最高的答案似乎根本不适用。它解释了iter的功能,但没有解释为什么需要这样做的意义所在。(它还解释了为什么iter需要__iter__,这与这个问题更无关。) - user4815162342
自从我最初投票关闭以来,这里出现了一些更好(而且切题)的答案,所以我倾向于同意这是错误的。 - Charles Duffy
显示剩余2条评论
4个回答

6
除了使用 iter 来显式地获取实现了 __iter__ 方法的对象的迭代器外,还有一种不太常见的 iter 的两个参数形式,它可以创建一个迭代器,该迭代器反复调用一个函数,直到函数返回给定的标记值。
 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
+1 很棒的回答,涵盖了iter的“正常”用法和两个参数形式。你可能需要更准确地说明迭代器可以是与其迭代的对象不同的独立对象。许多对象,尤其是文件对象,以及迭代器本身,都是它们自己的迭代器。 - user4815162342

5
< p > 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)

非常好,一个实际的例子是创建同一可迭代对象的多个迭代器。 - chepner

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

但是,在Python中,可迭代对象还允许你做一些其他的事情,比如使用next()来遍历一个可迭代对象,或者引发一个StopIteration异常。如果你正在处理不同的对象类型,并且想应用一个通用的算法,这可能会很有用。

0

文档中:

iter(o[, sentinel])

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

因此,它从一个对象构造一个迭代器。

正如你所说,在循环和推导式中,这是自动完成的,但有时你想获取一个迭代器并直接处理它。只需将其记在脑后,直到你需要它。

当使用第二个参数时:

如果给定了第二个参数sentinel,那么o必须是一个可调用对象。 在这种情况下创建的迭代器将在每次调用其next()方法时无参数地调用o; 如果返回的值等于sentinel,则会引发StopIteration异常,否则将返回该值。

这对于许多事情都很有用,特别是对于像file.read(bufsize)这样的传统风格函数尤其如此,它必须重复调用直到返回""。可以使用iter(lambda : file.read(bufsize), "")将其转换为迭代器。简洁明了!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接