ZetCode

Python 迭代器

最后修改于 2024 年 1 月 29 日

Python 迭代器教程展示了如何在 Python 中使用迭代器。

迭代器

迭代 是遍历集合中元素的過程。可迭代对象 是可以被迭代的对象。迭代器 是一个允许遍历集合中所有元素的对象,无论其具体实现如何。它会从其关联的可迭代对象中生成连续的值。

在 Python 中,迭代器是一个实现了迭代器协议的对象。迭代器协议包含两个方法:`__iter__` 方法,它必须返回迭代器对象;`next` 方法,它返回序列中的下一个元素。内置函数 `iter` 用于从可迭代对象中获取迭代器。

如果迭代器中的所有值都已返回,则后续调用 `next` 函数会引发 `StopIteration` 异常。

迭代器有几个优点

Python 有几个内置对象实现了迭代器协议。例如列表、元组、字符串、字典或文件。

Python 迭代器简单示例

以下简单示例使用了字符串对象的迭代器。

simple_it.py
#!/usr/bin/python

text = "falcon"

it = iter(text)

print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))

在代码示例中,我们对字符串使用了内置迭代器。在 Python 中,字符串是字符的不可变序列。

it = iter(text)

`iter` 函数返回一个对象的迭代器。

print(next(it))

`next` 函数返回可迭代对象的下一个元素。

$ ./simple_it.py
f
a
l
c
o
n

Python 迭代器和 for 循环

for 循环是在 Python 中处理迭代器的常用方法。for 循环执行以下操作:

for e in vals:
   print(e)

循环体对 `next` 返回的每个项目执行一次。变量 `e` 在每次迭代时被设置为给定的项目。

for_loop.py
#!/usr/bin/python

text = "an old falcon"

for val in text:
    print(val, end=" ")

print()

在示例中,我们通过 for 循环遍历文本。我们打印每个字符,并在它们之间添加空格。

$ ./for_loop.py
a n   o l d   f a l c o n

list、tuple 和 set 内置函数

当我们在可迭代对象上使用 `list`、`tuple` 和 `set` 内置函数时,我们会强制迭代器返回所有项目。请注意,有些可迭代对象可能非常大。

list_tuple_set.py
#!/usr/bin/python

text = "an old falcon"

data = list(text)
print(data)

data2 = tuple(text)
print(data2)

data3 = set(text)
print(data3)

在示例中,我们使用 `list`、`tuple` 和 `set` 内置函数来生成给定文本的字符列表、元组和集合。

$ ./list_tuple_set.py
['a', 'n', ' ', 'o', 'l', 'd', ' ', 'f', 'a', 'l', 'c', 'o', 'n']
('a', 'n', ' ', 'o', 'l', 'd', ' ', 'f', 'a', 'l', 'c', 'o', 'n')
{'f', 'd', 'n', 'o', 'a', ' ', 'c', 'l'}

Python 迭代器读取行

当使用迭代器从文件中读取数据时,我们可以获取下一行而不必将整个文件读入内存。这样我们就可以节约系统资源。

words.txt
blue
sky
cloud
winter
blow
water
falcon

这是 words.txt 文件。

read_data_iterator.py
#!/usr/bin/python

with open('words.txt', 'r') as f:

    for line in f:
        print(line.rstrip())

`open` 函数返回一个文件对象,它是一个迭代器。我们可以在 for 循环中使用它。通过使用迭代器,代码会更简洁。

$ ./read_data_iterator.py
blue
sky
cloud
winter
blow
water
falcon

Python 自定义迭代器

要创建自定义迭代器,它必须实现迭代器协议:`__iter__` 和 `__next__` 函数。

inf_seq.py
#!/usr/bin/python

class InfSeq:

   def __init__(self):
       
      self.x = 0

   def __next__(self):
   
      self.x += 1
      return self.x ** self.x

   def __iter__(self):
       
      return self


infseq = InfSeq()
n = 0

for e in infseq:

   print(e)
   n += 1
   
   if n > 10:
      break

在代码示例中,我们创建了一个数字序列 1, 4, 27, 256, ... 。这表明通过迭代器,我们可以处理无限序列。

def __iter__(self):
    
    return self

for 语句在容器对象上调用 `__iter__` 函数。该函数返回一个迭代器对象,该对象定义了 `__next__` 方法,该方法一次访问一个元素。

def next(self):

    self.x += 1
    return self.x ** self.x

`next` 函数返回序列的下一个元素。

if n > 10:
    break

由于我们处理的是无限序列,因此必须在某个时候中断 for 循环。

$ ./inf_seq.py 
1
4
27
256
3125
46656
823543
16777216
387420489
10000000000
285311670611

StopIteration

迭代过程通过引发 `StopIteration` 异常来终止。

random_words.py
#!/usr/bin/python

import random

class RandomWord:

    def __init__(self):

        self.words = ['sky', 'blue', 'cloud', 'milk', 'cosmos',
            'rainbow', 'drop', 'new', 'stop']

    def __iter__(self):
        return self

    def __next__(self):

        random_word = random.choice(self.words)

        if random_word == 'stop':

            raise StopIteration  

        else:
            return random_word

rw = RandomWord()

for word in rw:
    print(word)

在代码示例中,我们有一个产生随机单词的自定义迭代器。当选到停止词时,我们会引发 `StopIteration` 异常。

$ ./random_words.py 
sky
blue
new
drop
milk
drop
milk
drop
blue

来源

Python 迭代器对象

在本文中,我们研究了 Python 中的迭代器。

作者

我叫 Jan Bodnar,是一名充满激情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有超过十年的经验。

列出所有 Python 教程