0%

Python小技巧(4)--迭代器

迭代器----来源于cookbook第四章

记录第四章中比较有意思的部分


实现容器的委托迭代

只需要为容器实现__iter__魔法方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

class Node:
def __init__(self,value):
self._value = value
self._children = []

def __repr__(self):
return "Node({!r})".format(self._value)

def add_child(self,value):
self._children.append(value)

def __iter__(self):
return iter(self._children)

a = Node("list")
a.append(1)
a.append(2)
for i in a:
print(i,end="") ## 12

简单的方法实现迭代协议

使用yield from即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

def gen():
x = [1,2,3,4,5]
# 注意,此处yield出去的仍然是一个迭代器,
yield (i for i in x if i > 3)

a = gen()
for i in a:
print(i) # <generator object gen.<locals>.<genexpr> at 0x000001C6FC019D60>



def gen_good():
x = [1,2,3,4,5]
# 此时yield出去的是我们需要的整数
yield from (i for i in x if i > 3)

a = gen()
for i in a:
print(i) # 4 5

反向迭代

只需要实现__reversed__()方法即可,实现反向迭代后的效率更高

迭代器切片

使用itertoolsislice()方法即可

1
2
3
4
5
6
7
8
9
10
11
12

from itertools import islice

def gen():
for i in range(20):
yield i

for i in islice(gen(),10,20):
print(i) # 10....19

# 但是注意,islice会消耗掉迭代器,所以没法倒回去访问数据

以索引-值的形式迭代序列

使用enumerate()即可

1
2
3
4
5
6

a = ['a','b','c']

for index, word in enumerate(a):
print(index,word) # 0 a 1 b 2 c

同时迭代多个序列

使用zip()函数即可,其返回一个迭代器,长度是参数中较短的一个

1
2
3
4
5
6
7

a = [1,2,3]
b = [4,5,6,7]

for x,y in zip(a,b):
print(x,y) # 1 4 2 5 3 6

在多个容器中进行迭代

使用itertoolschain()函数即可,可以逐个迭代多个容器

1
2
3
4
5
6
7
8
9
10

from itertools import chain

a = [1,2,3]
b = [4,5,6,7]

for i in chain(a,b):
print(i) # 1 2 3 4 5 6 7


使用迭代器取代while循环

iter(func,sentinal)可以一直调用无参函数func直到其返回哨兵值sentinal为止

这样就可以将while循环转换成迭代器模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14

times = 1

def gen():
global times
if times==10:
return -1
times +=1
return 1

for i in iter(gen,-1):
print(i)