可迭代的对象、迭代器和生成器
import re
import reprlib
RE_WORD = re.compile('\w+')
class Sentence_v1:
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)
s = Sentence_v1('"The time has come," the Walrus said,')
print(repr(s))
for word in s:
print(word)
Sentence('"The time ha... Walrus said,')
The
time
has
come
the
Walrus
said
当解释器需要迭代对象时,
__iter__
__getitem__
- 抛出
TypeError
class Foo:
def __iter__(self):
pass
from collections import abc
print(issubclass(Foo, abc.Iterable))
f = Foo()
print(isinstance(f, abc.Iterable))
True
True
s = 'ABC'
for char in s:
print(char)
A
B
C
s = 'ABC'
it = iter(s)
while True:
try:
print(next(it))
except StopIteration:
del it
break
A
B
C
import re
import reprlib
RE_WORD = re.compile('\w+')
class Sentence_v2:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text)
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
__iter__
实例化并返回一个迭代器
import re
import reprlib
RE_WORD = re.compile('\w+')
class Sentence_v3:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text)
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self):
for word in self.words:
yield word
return # 可有可无
yield
惰性求值
# yield
def gen_AB():
print('start')
yield 'A'
print('continue')
yield 'B'
print('end') # 第三次迭代到这里后, 抛出异常, 被 for 捕捉, 停止迭代
for c in gen_AB():
print('--> ', c)
start
--> A
continue
--> B
end
import re
import reprlib
RE_WORD = re.compile('\w+')
class Sentence_v4:
def __init__(self, text):
self.text = text
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self):
for match in RE_WORD.finditer(self.text):
yield match.group()
惰性求值与迫切求值
l1 = [x for x in gen_AB()]
start
continue
end
for x in l1:
print(x)
A
B
g1 = (x for x in gen_AB())
for x in g1:
print(x)
start
A
continue
B
end
import re
import reprlib
RE_WORD = re.compile('\w+')
class Sentence_v5:
def __init__(self, text):
self.text = text
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self): # 直接返回一个 iter
return (match.group() for match in RE_WORD.finditer(self.text))
无限等差数列
class ArithmeticProgression:
def __init__(self, begin, step, end=None):
self.begin, self.step, self.end = begin, step, end
def __iter__(self):
result = type(self.begin + self.step)(self.begin) 将
forever = self.end is None
index = 0
while forever or result < self.end:
yield result
index += 1
result = self.begin + self.step * index
def aritprog_gen(begin, step, end=None):
result = type(begin + step)(begin)
forever = end is None
index = 0
while forever or result < end:
yield result
index += 1
result = begin + step * index
itertools 中的 等差数列
import itertools
gen = itertools.count(1, .5)
print(next(gen))
print(next(gen))
print(next(gen))
1
1.5
2.0
itertools.takewhile
生成一个使用另一个生成器的生成器, 仅在计算结果为 False 时停止
gen2 = itertools.takewhile(lambda n: n < 3, itertools.count(1, .5))
print(list(gen2))
[1, 1.5, 2.0, 2.5]
def aritprog_gen2(begin, step, end=None):
first = type(begin + step)(begin)
ap_gen = itertools.count(first, step)
if end is not None:
ap_gen = itertools.takewhile(lambda n: n < end, ap_gen)
return ap_gen
标准库中的生成器
用于过滤的生成器函数
模块 | 函数 | 说明 |
---|---|---|
itertools |
compress(it, selector_it) |
并行处理两个 iter , 如果 selector_it 中元素为真, 则产出对应 it 中的元素 |
itertools |
dropwhile(predicate, it) |
处理 it , 跳过 predicate 中计算结果为真的元素, 然后查出剩下的各个元素(不再进一步检查) |
(inner) |
filter(predicate, it) |
把 it 中的各个元素传给 predicate, 如果 predicate(item) 返回真, 那么产出对应元素 |
itertools |
filterfalse(predicate, it) |
与上面相反 |
itertools |
islice(it, stop) 或 islice(it, start, stop, step=1) |
产出 it 切片, 作用类似于 s[:stop] 或 s[start:stop:step], 但返回的是一个可迭代对象 |
itertools |
takewhile(predicate, it) |
predicate 返回真值时产出对应的元素, 然后立即停止, 不在继续检查 |
from itertools import filterfalse, dropwhile, takewhile, compress, islice
def vowel(c):
return c.lower() in 'aeiou'
print('filter: ', list(filter(vowel, 'Aardvark'))) # 产出所有 aeiou
print('filterfalse: ', list(filterfalse(vowel, 'Aardvark'))) # 产出所有 除了aeiou
print('dropwhile: ', list(dropwhile(vowel, 'Aardvark'))) # 从第一个不是 aeiou 的元素开始产出到末尾
print('takewhile: ', list(takewhile(vowel, 'Aardvark'))) # 从第一个元素开始产出 到不是 aeiou 的元素停止
print('compress: ', list(compress('Aardvark', (1, 0, 1, 1, 0, 1)))) # 产出 后面 it 为真的元素
print('islice: ', list(islice('Aardvark', 1, 7, 2))) # 类似于切片
filter: ['A', 'a', 'a']
filterfalse: ['r', 'd', 'v', 'r', 'k']
dropwhile: ['r', 'd', 'v', 'a', 'r', 'k']
takewhile: ['A', 'a']
compress: ['A', 'r', 'd', 'a']
islice: ['a', 'd', 'a']
用于映射的生成器函数
模块 | 函数 | 说明 |
---|---|---|
itertools |
accumulate(it, func=sum) |
每次将前两个元素传给 func, 产出计算结果, 默认 func=sum |
(inner) |
enumerate(iterable, start=0) |
每次产出(index, item), index 从 start 开始, 默认为 0 |
(inner) |
map(func, it1, it2, it3 ...) |
把 it 中的各个元素传给 func, 产出结果, 多个 it 时, 并行处理, func(it1, it2, it3 ...), 遍历次数取最小 it |
itertools |
starmap(func, it) |
把 it 中各个元素传给 func, 产出结果, 输入的 it 应产出 可迭代对象 iit, 以 func(*iit) 的形式调用 func |
from itertools import accumulate, starmap
from operator import mul
sample = [5, 4, 2, 8, 7, 6, 3, 0, 9, 1]
print('accumulate sum(default): ', list(accumulate(sample)))
print('accumulate min: ', list(accumulate(sample, min)))
print('accumulate max: ', list(accumulate(sample, max)))
print('accumulate mul: ', list(accumulate(sample, mul)))
print('accumulate fact: ', list(accumulate(range(1, 11), mul)))
accumulate sum(default): [5, 9, 11, 19, 26, 32, 35, 35, 44, 45]
accumulate min: [5, 4, 2, 2, 2, 2, 2, 0, 0, 0]
accumulate max: [5, 5, 5, 8, 8, 8, 8, 8, 9, 9]
accumulate mul: [5, 20, 40, 320, 2240, 13440, 40320, 0, 0, 0]
accumulate fact: [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
print('enumerate: ', list(enumerate('Ryugu Reina', 1)))
print('map', list(map(mul, range(11), range(11))))
print('map', list(map(mul, range(11), range(3)))) # 取最小长度
print('starmap', list(starmap(mul, enumerate('Ryugu Reina', 1))))
print('starmap', list(starmap(lambda a, b: b / a, enumerate(accumulate(sample), 1))))
enumerate: [(1, 'R'), (2, 'y'), (3, 'u'), (4, 'g'), (5, 'u'), (6, ' '), (7, 'R'), (8, 'e'), (9, 'i'), (10, 'n'), (11, 'a')]
map [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
map [0, 1, 4]
starmap ['R', 'yy', 'uuu', 'gggg', 'uuuuu', ' ', 'RRRRRRR', 'eeeeeeee', 'iiiiiiiii', 'nnnnnnnnnn', 'aaaaaaaaaaa']
starmap [5.0, 4.5, 3.6666666666666665, 4.75, 5.2, 5.333333333333333, 5.0, 4.375, 4.888888888888889, 4.5]
合并多个可迭代对象的生成器
模块 | 函数 | 说明 |
---|---|---|
itertools |
chain(it1, it2, ...) |
将各个 it 拼接在一起 |
itertools |
chain.from_iterable(it1) |
将各个 it 产出的 iit 拼接在一起 |
itertools |
product(it1, it2, ..., repeat=1) |
计算笛卡尔积, repeat 重复处理多少次 |
(inner) |
zip(it1, it2, ...) |
将各个 it 中的元素并行组成元组 |
itertools |
zip_longest(it1, it2, ..., fillvalue=None) |
同上, 短的 it 用 fillvalue 填充 |
from itertools import chain, zip_longest, product
print('chain: ', list(chain('abc', range(2))))
print('chain.from_iterable:', list(chain.from_iterable(enumerate('abc'))))
print('zip: ', list(zip('abc', range(10))))
print('zip_longest: ', list(zip_longest('abc', range(10), fillvalue='q')))
chain: ['a', 'b', 'c', 0, 1]
chain.from_iterable: [0, 'a', 1, 'b', 2, 'c']
zip: [('a', 0), ('b', 1), ('c', 2)]
zip_longest: [('a', 0), ('b', 1), ('c', 2), ('q', 3), ('q', 4), ('q', 5), ('q', 6), ('q', 7), ('q', 8), ('q', 9)]
print('product', list(product('ABC', range(2))))
suits = 'spades hearts diamonds clubs'.split()
print('product', list(product('AK', suits)))
print('product', list(product('ABC')))
print('product', list(product('AB', repeat=3))) #<==> ('AB', 'AB', 'AB')
product [('A', 0), ('A', 1), ('B', 0), ('B', 1), ('C', 0), ('C', 1)]
product [('A', 'spades'), ('A', 'hearts'), ('A', 'diamonds'), ('A', 'clubs'), ('K', 'spades'), ('K', 'hearts'), ('K', 'diamonds'), ('K', 'clubs')]
product [('A',), ('B',), ('C',)]
product [('A', 'A', 'A'), ('A', 'A', 'B'), ('A', 'B', 'A'), ('A', 'B', 'B'), ('B', 'A', 'A'), ('B', 'A', 'B'), ('B', 'B', 'A'), ('B', 'B', 'B')]
把输入的各个元素扩展成多个输出元素的生成器
模块 | 函数 | 说明 |
---|---|---|
itertools |
combinations(it, out_len) |
把 it 产出的 out_len 个元素组合在一起, 然后产出, 即 out_len 个元素的组合 |
itertools |
combinations_with_replacement(it, out_len) |
把 it 产出的 out_len 个元素组合在一起, 然后产出, 包含相同元素的组合 |
itertools |
count(start=0, step=1) |
从 start 开始产出数字, 步长为 step |
itertools |
rpcle(it, out_len) |
把 it 产出的元素存储, 不断重复产出 |
itertools |
permutations(it, out_len=len(list(it))) |
把 out_len 个产出的元素排列在一起, 然后产出这些排列, 即 out_len 个元素的排列 |
itertools |
repeat(item, [times]) |
重复产出 item, 除非提供 times |
from itertools import count, cycle, repeat, combinations, combinations_with_replacement, permutations, islice
ct = count()
print('count: ', next(ct), next(ct), next(ct))
print('count & islice: ', list(islice(count(1, .3), 3)))
cy = cycle('RUA')
print('cycle: ', next(cy), next(cy), next(cy), next(cy), next(cy), next(cy))
rp = repeat(6)
print('repeat: ', next(rp), next(rp), next(rp))
print('repeat: ', list(repeat(8, 4)))
print('repeat: ', list(map(mul, range(11), repeat(5))))
print('combinations', list(combinations('ABC', 2)))
print('combinations', list(combinations_with_replacement('ABC', 2)))
print('combinations', list(combinations('ABC', 1)))
print('permutations', list(permutations('ABC', 2)))
count: 0 1 2
count & islice: [1, 1.3, 1.6]
cycle: R U A R U A
repeat: 6 6 6
repeat: [8, 8, 8, 8]
repeat: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
combinations [('A', 'B'), ('A', 'C'), ('B', 'C')]
combinations [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
combinations [('A',), ('B',), ('C',)]
permutations [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
用于重新排列的元素生成器
模块 | 函数 | 说明 |
---|---|---|
itertools |
groupby(it, key=None) |
产出由两个元素组成的元素 (key, group) |
(inner) |
reversed(seq) |
倒序产出 seq 中的元素, seq 必须是序列, 或者实现了 __reversed__ |
itertools |
tee(it, n=2) |
产出由 n 个元素组成的元组 |
from itertools import groupby, tee
print(list(groupby('LLLLLLLAAAAAAGGGGGGGGGGGGGGGGGGGGGGGGG')))
for key, group in groupby('LLLLLLLAAAAAAGGGGGGGGGGGGGGGGGGGGGGGGG'):
print(key, '-->', list(group))
print()
for key, group in groupby(['rua', 'aur', 'rau', 'aaaa', 'afeswr', 'sgse'], key=len): # 按长度分组, 最好先排个序 -_-|
print(key, '-->', list(group))
print()
for key, group in groupby(reversed(['rua', 'aur', 'rau', 'aaaa', 'afeswr', 'sgse']), key=len): # 从右向左迭代列表
print(key, '-->', list(group))
print()
g1, g2 = tee('ABC') # 产出多个相同的迭代器
print('tee', next(g1), next(g2), next(g1))
[('L', <itertools._grouper object at 0x000001E3B5D93760>), ('A', <itertools._grouper object at 0x000001E3B5D93A30>), ('G', <itertools._grouper object at 0x000001E3B5D91390>)]
L --> ['L', 'L', 'L', 'L', 'L', 'L', 'L']
A --> ['A', 'A', 'A', 'A', 'A', 'A']
G --> ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G']
3 --> ['rua', 'aur', 'rau']
4 --> ['aaaa']
6 --> ['afeswr']
4 --> ['sgse']
4 --> ['sgse']
6 --> ['afeswr']
4 --> ['aaaa']
3 --> ['rau', 'aur', 'rua']
tee A A B
yield from
def chain_(*iterables):
for it in iterables:
for i in it:
yield i
print(list(chain_('APPLE', range(3))))
['A', 'P', 'P', 'L', 'E', 0, 1, 2]
def chain_(*iterables):
for it in iterables:
yield from it
print(list(chain_('APPLE', range(3))))
['A', 'P', 'P', 'L', 'E', 0, 1, 2]
可迭代规约函数
模块 | 函数 |
---|---|
(inner) |
all(it) |
(inner) |
any(it) |
(inner) |
max(it, [it2], ..., [key], [default]) |
(inner) |
min(it, [it2], ..., [key], [default]) |
functools |
reduce(func, it, [initial]) |
(inner) |
sum(it, start=0) |
iter 函数
python 在迭代对象时会调用 iter(x)
iter(v, w)
其中, w
是哨符, 当生成器产出这个对象时, 会抛出 StopIteration
, 停止迭代
from random import randint
def d6():
return randint(1, 6)
d6_iter = iter(d6, 1)
for roll in d6_iter: # 抛到 1 停止
print(roll, end=' ')
3 6 2 4
标签:__,迭代,Python,list,self,生成器,itertools,print,def
From: https://www.cnblogs.com/Zinc233/p/FluentPython_S14.html