0. 前言
参考资料:
《Python Cookbook》第四章 《流畅的Python》第十四章 《深入理解Python特性》第六章 迭代器和生成器属于同一概念,生成器可看作是简化版的迭代器。
1. 解析式
解析式类型:
解析式都是语法糖,可以条件规律元素。 举例:
squares = [ x* x for x in range ( 10 ) if x % 2 == 0 ]
squares_set = { x* x for x in range ( 10 ) }
squares_dict = { x: x* x for x in range ( 5 ) }
2. 迭代器
2.1. 迭代器模式
迭代器模式可用来:
访问一个聚合对象的内容而无需暴露它的内部表示。 支持对聚合对象的多种遍历。 为遍历不同的聚合结构提供一个统一的接口(即支持多态迭代)。
2.2. 可迭代对象与迭代器
可迭代对象:
使用 iter
函数可以获取迭代器的对象。 抽象基类:collections.abc.Iterable
。 迭代器:
实现了无参数的 __next__
方法,返回序列中的下一个元素。如果没有元素,则抛出 StopIteration
异常。 抽象基类:collections.abc.Iterator
。 不建议可迭代对象和迭代器实现在一个类中:
2.3. iter函数
解释器需要迭代对象时,会自动调用 iter
函数。
iter
函数的另外一种用法:iter(a, flag)
,第一个参数是可调用对象,第二个参数是哨兵符,当可调用对象返回这个哨兵符时,抛出异常,不返回值。 作用:
检查是否实现 __iter__
方法,如果实现了就调用,获取迭代器。 如果没有实现 __iter__
方法,但实现了 __getitem__
方法,就会自动创建一个迭代器,尝试按顺序(从0开始)获取元素。 如果尝试失败,则抛出 TypeError
并提示 XX Object is not iterable
。 如果类实现了 __iter__
方法,则 issubclass(Foo, abc.Iterable)
取值为 True
。
2.4. for-in 循环在 Python 中的工作原理
repeater = Repeater('Hello')
for item in repeater:
print(item)
repeater = Repeater('Hello')
iterator = repeater.__init__()
while True:
item = iterator.__next__()
print(item)
2.5. 迭代器实例
典型迭代器(《流畅的Python》示例14-4)
迭代器和可迭代对象分开。 这样比较清晰,符合设计模式,但很麻烦。
import re
import reprlib
RE_WORD = re. compile ( '\w+' )
class Sentence :
def __init__ ( self, text) :
self. text = text
self. words = RE_WORD. findall( test)
def __repr__ ( self) :
return 'Sentence(%s)' % reprlib. repr ( self. text)
def __iter__ ( self) :
return SentenceIterator( self. words)
class SentenceIterator :
def __init__ ( self, words) :
self. words = words
self. index = 0
def __next__ ( self) :
try :
word = self. words[ self. index]
except IndexError:
raise StopIteration( )
self. index += 1
return word
def __iter__ ( self) :
return self
import re
import reprlib
RE_WORD = re. compile ( '\w+' )
class Sentence :
def __init__ ( self, text) :
self. text = text
self. words = RE_WORD. findall( test)
self. index = 0
def __repr__ ( self) :
return 'Sentence(%s)' % reprlib. repr ( self. text)
def __next__ ( self) :
try :
word = self. words[ self. index]
except IndexError:
raise StopIteration( )
self. index += 1
return word
def __iter__ ( self) :
return self
3. 生成器
3.1. 基本生成器
两种形式:
类形式的生成器:定义 __iter__
方法,并在该方法中使用 yield
关键字。
函数形式的生成器:使用yield
替代return
。
调用生成器函数就会返回一个生成器对象。 生成器函数就是生成器工厂。 生成器函数的工作原理(以函数形式为例):
当第一次调用生成器时,从函数开头开始运行,到第一个yield
结束。 当第二次(或多次)调用生成器时,从上一次结束的 yield
语句开始运行程序。 特点:惰性实现。尽可能延后生成值,从而节约内存,避免无用处理。
3.2. 生成器表达式
与列表表达式的定义方式非常类似,区别在于列表表达式使用[]
,而生成器表达式使用 ()
可理解为列表推导的惰性版本:不会迫切构建列表,而是返回一个生成器,按需惰性生成元素。 生成器表达式是语法糖,完全可以替换生成器函数。 生成器表达式与普通生成器的选择:
如果生成器表达式要分成多行,则尽量用生成器函数,以便提高可读性。 yield from
:生成器函数需要产生另一个生成器生成的值,可以通过嵌套for循环,也可以使用 yield from
。举例:
iterator = ( 'Hello' for i in range ( 3 ) )
def bounded_repeater ( value, max_repeats) :
for i in range ( max_repeats) :
yield value
3.3. 标准库中的生成函数
itertools
compress
dropwhile
filterfalse
islice
takewhile
accumulate
startmap
内置:
举例:
通过 itertools.islice()
函数可以对迭代器做切片操作。 通过 itertools.dropwhile()
来跳过可迭代对象中的前一部分元素。 通过 itertools.permutations()
来获取所有可能的组合或排列。 通过 enumerate
获取索引+值的迭代序列。 通过 zip
同时迭代多个序列。 通过 itertools.chain
在不同容器中进行迭代。 通过 heapq.merge()
合并多个有序序列。
3.4. 生成器实例
class Test :
def __iter__ ( self) :
for i in range ( 10 ) :
yield i
def gen_123 ( ) :
print ( 'start' )
yield 1
print ( 'continue' )
yield 2
print ( 'final' )
yield 3
4. 迭代器链
基本概念:
链接多个迭代器,或者说,多个迭代器嵌套使用。 另一种理解,将生成器产生的数据看作流 ,迭代器链就是将这个数据流在多个迭代器形成的管道中流过。 特点:
实例(来自《深入理解Python特性》6.7节)
def integers ( ) :
for i in range ( 1 , 9 ) :
yield i
def squared ( seq) :
for i in seq:
yield i * i
def negated ( seq) :
for i in seq:
yield - i
chain = negated( squared( integers( ) ) )
print ( list ( chain) )