可迭代对象、迭代器、生成器
2018-01-19 本文已影响92人
一块大番薯
序列协议
只要实现了_getitem_ 和 _len_ 就可以看做是序列
import re
import reprlib
RE_WORD = re.compile('\w+')
class Sentence:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text)
def __getitem__(self, index):
return self.words[index]
def __len__(self):
return len(self.words)
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
序列协议
可迭代原因:iter 函数
迭代对象的流程:
- 检查对象是否实现了 _iter_,是,则调用它获取一个迭代器
- 否,检查对象是否实现了 _getitem_,是,则创建一个迭代器从索引 0 开始获取元素
- 否,抛出 TypeError
可迭代对象与迭代器
关系:Python 从 可迭代对象中获取迭代器
s = 'ABC'
it = iter(s) # 用可迭代对象构建迭代器
while True:
try:
print(next(it))
except StopIteration: # for循环,列表推导,元祖拆包也会有
del it
break
生成器函数
定义:定义体中含有 yield 关键字的函数。调用生成器函数返回生成器对象。生成器产出值。
生成器函数
生成器函数执行过程
生成器表达式
惰性,当 for 循环迭代时,才会执行函数定义体
生成器表达式
标准库生成器函数
- filter(predicate, it)
接受一个断言参数 predicate 和一个迭代器参数。当 predicate(item) 为 True 时,保留。 - enumerate(it, start=0)
产出 (index, item),其中 index 从start 开始计数。 - map(func, it)
产出 func(item) - zip(it1, ..., itN)
产出由 N 个元素组成的元祖,只有有一个可迭代对象迭代尽了就停止。 - itertools.zip_longest(it1, ..., itN, fillvalue=None)
- itertools.chain(it1, ..., itN)
- reversed(seq)
倒序产出 seq 元素
yield from
不同生成器结合在一起使用。
代替嵌套迭代,直接与最内层生成器联系起来。
yield from
可迭代的归约函数
- all(it)
- any(it)
- max(it, [key=, default=])
- min(it, [key=, default=])
- reduce(func, it[, initial])
- sum(it, start=0)
虽然每个归约函数都可以用 functools.reduce 来代替,但有一项优化措施 reduce 做不到:一旦确定结果立即停止迭代
all([])
I already read the docs, and I know the implementation
def all(iterable):
for element in iterable:
if not element:
return False
return True
But the question is why not?
def all(iterable):
if not iterable:
return False
for element in iterable:
if not element:
return False
return True
深入分析 iter 函数
iter- iter 的第一个参数是可调用对象,不断产生值,第二个参数是哨符,当产出这个值时,抛出 StopIteration,停止迭代。