探索迭代器模式:Python技术专家豌豆花下猫的深度解析与设计模式应用

豌豆花下有一只猫,它是某 985 高校的毕业生,既具备极客思维又富有人文情怀。公众号 Python 猫,将精力集中在 python 技术、数据科学和深度学习方面,一心想要创造出一个既有趣又有用的学习分享平台。

探索迭代器模式:Python技术专家豌豆花下猫的深度解析与设计模式应用

[id_1403[id_1771062223]84392]《设计模式:可复用面向对象软件的基础》(1991 年出版)这本圣经级书籍中,提出了 23 种设计模式。其中有一种是迭代器模式,它在各种编程语言里都获得了广泛的应用。

本文将谈论 Python 中的迭代器模式。主要内容包括:什么是迭代器模式;Python 是如何实现迭代器模式的;itertools 模块创建迭代器的具体方法;以及其他运用迭代器的场景等。期待与你一同学习进步。

1、什么是迭代器模式?

维基百科有如下定义:

迭代器是一种设计模式。它最为简单且最为常见。用户能够透过特定的接口去巡访容器中的每一个元素。并且在这个过程中不用去了解底层的实现。

简单来说,迭代器模式是一种通用性的实现方式,能够遍历容器类型,像序列类型、集合类型等。运用迭代器模式,无需关心遍历的对象具体为何,比如字符串、列表、字典等,也不必在意遍历的实现算法是什么,只需关注从容器中遍历或取出元素的结果。

按遍历方式来划分的话,迭代器可以分为内部迭代器和外部迭代器。内部迭代器和外部迭代器的区别在于执行迭代动作的方式不同,并且维持迭代状态的方式也不同。

一般来讲,迭代器具有一次性的特点。当完成一轮迭代之后,再次进行迭代就无法获取到元素了。

2、Python的迭代器模式

因为迭代器模式的使用较为普遍,所以多数编程语言都为常见的容器类型实现了它。比如在 Java 中,像 Collection、List、Set、Map 等这些常见的容器类型就都有了迭代器的实现。在 Java 中要使用迭代器来遍历 List 的话,可以这样写:

List list = new ArrayList<>();
Iterator iterator = list.iterator();
while(iterator.hasNext()){
输出迭代器的下一个元素。具体来说,就是通过调用 iterator 的 next 方法,然后将其返回值在控制台进行输出显示。
}

ArrayList 类利用自身的 iterator() 方法获取到一个迭代器 iterator 。接着,由这个迭代器实例来进行遍历过程的实施。

它的实现思路与上例不同。

Python 认为,遍历容器类型不一定非得用到迭代器。基于此,它设计了可迭代对象。

list = [1,2,3,4]
for i in list:
    print(i,end=" ") # 1 2 3 4
for i in list:
    print(i,end=" ") # 1 2 3 4

上例中的 list 属于可迭代对象。它可以被迭代。但它本身并不是迭代器。尽管在底层实现时运用了迭代器的部分思想。Python 抓住了迭代器模式的本质,也就是“迭代”。并且赋予了它非常高的地位。

这种设计的好处较为明显:其一,写法较为简便,用意也较为直白;其二,能够进行重复迭代,从而避免了一次性迭代器所存在的缺陷;其三,无需创建迭代器,这样就能减少开销。

可迭代对象可被看作是一种广义的迭代器。并且,Python 设计了具有普通意义的狭义的迭代器。

list = [1,2,3,4]
it = iter(list)
for i in it:
    print(i,end=" ") # 1 2 3 4
for i in it:
    print(i,end=" ") # 无输出

上例中的 iter() 方法能把可迭代对象转化为一个迭代器。从输出结果能够得知,这个迭代器的迭代过程是仅一次的。

由此看来,Python 实现“迭代器模式”是通过将其拆分为两部分:一是可迭代思想,这种思想广泛存在于容器类型的对象中,使得这些对象都具备可迭代的特性;二是迭代器,它是一种特殊的可迭代对象,负责承担普通意义上迭代器所特有的迭代任务。

它提供了将可迭代对象转化为迭代器的方法,并且这种方法很简易。这样的安排使得迭代器模式的效力得以充分发挥,达到了极致的效果。

3、创建迭代器

- 还有其它创建方法,像 zip() 、map() 、enumerate() 等等。

四类方法分别有其适用的场所,在本节中,重点对 itertools 模块进行介绍。这个模块能够创建三种不同类型的迭代器,分别是无限迭代器、有限迭代器以及组合迭代器。

3.1 无限迭代器

创建一个从 0 开始,步长为 1 的无限整数迭代器,起始值为 start(默认值为 0),步长为 step(默认值为 1)。

对可迭代对象执行循环操作,这个循环操作针对可迭代对象的元素进行反复执行。

repeat(object, times) :会反复生成 object 直至达到给定的 times 次。

import itertools
co = itertools.count()
cy = itertools.cycle('ABC')
re = itertools.repeat('A', 30)

注意事项:请分别执行操作;以下所提供的写法未添加终止判断,仅能通过按下 Ctrl+C 组合键来退出。
for n in co:
    print(n,end=" ")  # 0 1 2 3 4......
for n in cy:
    print(n,end=" ")  # A B C A B C A B......
for n in re:
    print(n,end=" ")  # A A A A A A A A....(30个)

3.2 有限迭代器

以上方法中,较为常用的有:chain(),它能将多个可迭代对象(可以是不同类型)连接成一个大的迭代器;compress()方法,可依据真假过滤器来筛选元素;groupby(),能把迭代器中相邻的重复元素挑选出来并放在一起;islice()方法,可返回迭代器切片;tee()方法,能根据可迭代对象创建 n 个(默认 2 个)迭代器副本。

c 也依次遍历 [1, 2, 3] 中的元素。
    print(c,end=" ")
# 输出结果:A B C 1 2 3

for c in itertools.compress('ABCDEF', [1, 1, 0, 1, 0, 1]):
    print(c,end=" ")
# 输出结果:A B D F

for key, group in itertools.groupby('aaabbbaaccd'):
    print(key, ':', list(group))
# 输出结果:
a : ['a', 'a', 'a']
b : ['b', 'b', 'b']
a : ['a', 'a']
c : ['c', 'c']
d : ['d']

itertools.tee('abc', 3)
# 输出结果:(,
 at 0x1fc73f91d08>,
 at 0x1fc73efc248>)

3.3 组合迭代器

product() :求解多个可迭代对象的笛卡尔积。

permutations() 用于求解可迭代对象的元素的排列。

combinations():求解可迭代对象的元素的组合。

for i in itertools.product('ABC', [1,2]):
    print(i, end=" ")
# 输出结果:('A', 1) ('A', 2) ('B', 1) ('B', 2) ('C', 1) ('C', 2)

for i in itertools.permutations('ABC', 2):
    print(i, end=" ")
# 输出结果:('A', 'B') ('A', 'C') ('B', 'A') ('B', 'C') ('C', 'A') ('C', 'B')

for i in itertools.combinations('ABC', 2):
    print(i, end=" ")
# 输出结果:('A', 'B') ('A', 'C') ('B', 'C')

for i in itertools.combinations('ABCD', 3):
    print(i, end=" ")
# 输出结果:('A', 'B', 'C') ('A', 'B', 'D') ('A', 'C', 'D') ('B', 'C', 'D')

4、强大的内置迭代器方法

迭代器模式的使用场景十分普遍。Python 为迭代器的顺利使用提供了诸多便利条件。本节将介绍相关的几个内置方法。这些方法极为常用且强大,是 Python 进阶的必学内容。

4.1 zip() 方法

zip()方法能够同时对多个序列进行迭代,每个序列各取一个元素,从而生成一个可以返回元组的迭代器。这个迭代器的长度会与较短序列的长度保持相同。如果想要生成与较长序列长度一致的迭代器,就需要使用 itertools 模块中的 zip_longest()方法。

import itertools

a = [1, 2, 3]
b = ['w', 'x', 'y', 'z']

for i in zip(a,b):
    print(i,end=" ")  # (1, 'w') (2, 'x') (3, 'y')

# 空缺值以 None 填补
for i in itertools.zip_longest(a,b):
    print(i,end=" ")  # (1, 'w') (2, 'x') (3, 'y') (None, 'z')

4.2 enumerate() 方法

enumerate()方法会接收一个序列类型的参数,然后生成一个能够返回元组的迭代器,这个元组里面包含了下标以及与之对应的元素值。同时,它还可以接收一个可选的参数,用于指定下标的起始值,其默认值是 0 。

众所周知,在 Python 中序列的索引值是从 0 开始的。然而,enumerate()能够起到改变起始索引数值的作用。

seasons = ['Spring', 'Summer', 'Fall', 'Winter']

for i in enumerate(seasons):
    print(i,end=" ")  
#输出结果:(0, 'Spring') (1, 'Summer') (2, 'Fall') (3, 'Winter')

for i in enumerate(seasons, start=7):
    print(i,end=" ")  
#输出结果:(7, 'Spring') (8, 'Summer') (9, 'Fall') (10, 'Winter')

4.3 map() 方法

map()方法有一个参数,这个参数包含一个函数以及一个或多个可迭代对象。它会把可迭代对象的元素映射到那个函数里,接着迭代地运行该函数,最终返回的是一个迭代器。要是有多个可迭代对象参数的话,迭代的长度与较短对象的长度是相等的。

def square(x):
    return x ** 2

l = map(square, [1, 2, 3, 4, 5])
print(list(l))
# 输出结果:[1, 4, 9, 16, 25]

m = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10, 2])
print(list(m))
# 输出结果:[3, 7, 11, 15, 19]

4.4 filter() 方法

filter()方法的参数包含一个判断函数以及一个可迭代对象。它会遍历可迭代对象并执行判断函数,将判断为 True 的元素过滤掉。与之相对的是,如果想要保留判断为 False 的元素,那么可以使用 itertoole 模块中的 filterfalse()方法。

import itertools

fi = filter(lambda x: x%2, range(10))
ff = itertools.filterfalse(lambda x: x%2, range(10))

for i in fi:
    print(i,end=" ")
# 输出结果:1 3 5 7 9

for i in ff:
    print(i,end=" ")
# 输出结果:0 2 4 6 8

5. 小结

迭代器模式在 23 种设计模式中几乎是最常用的。本文主要介绍了 Python 运用迭代器模式的情况,还介绍了 itertools 模块生成迭代器的 18 种方法,以及 5 种生成迭代器的内置方法。

§§

Python 中文社区是一个去中心化的全球技术社区。它的愿景是成为全球 20 万 Python 中文开发者的精神部落。目前,它覆盖了各大主流媒体和协作平台。并且与阿里、腾讯、百度、微软、亚马逊、开源中国、CSDN 等业界知名公司和技术社区建立了广泛联系。它拥有来自十多个国家和地区的数万名登记会员。这些会员来自以公安部、工信部、清华大学、北京大学、北京邮电大学、中国人民银行、中科院、中金、华为、BAT、谷歌、微软等为代表的政府机关、科研单位、金融机构以及海内外知名公司。全平台近 20 万开发者对其予以关注。

你可能想看:
« 上一篇
下一篇 »

相关推荐

python爬虫教程PDF,Python爬虫书PDF

2026年09月02日

31阅读

外国教程python,python编程教学视频

2026年09月02日

25阅读

python简明教程沈洁元,python详细基础教程

2026年09月02日

21阅读

python库包教程,python 包

2026年09月02日

27阅读

python教程大全集,python教程600集

2026年09月02日

26阅读

python入门教程完整版,python零基础入门全套教程视频

2026年09月02日

22阅读