deffrange(start, stop, step):
x = start
while x < stop:yield x
x += step
这样,就可以得到一个浮点数序列:
f = frange(1.5,4.5,0.5)print(list(f))
结果:
[1.5,2.0,2.5,3.0,3.5,4.0]
只要出现了yield,函数就会转变为生成器,生成器中的元素只有在使用到时才生成
4.4 实现迭代协议
以下的类定义了一个树的节点:
classNode:def__init__(self, val):
self.val = val
self._children =[]def__iter__(self):returniter(self._children)defadd_child(self, child):
self._children.append(child)defdeep_first(self):yield self
for c in self:yieldfrom c.deep_first()
然后做一些初始化,构造出一棵树:
n = Node(0)
a = Node(1)
b = Node(2)
c = Node(3)
d = Node(4)
n.add_child(a)
n.add_child(b)
b.add_child(c)
a.add_child(d)
from collections import deque
classLineWithHistory:def__init__(self, lines, maxlen=3):
self._lines = lines
self.history = deque(maxlen=maxlen)def__iter__(self):for lineno, line inenumerate(self._lines,1):
self.history.append((lineno, line))yield line
defclear(self):
self.history.clear()
我们的文本文件内容是这样的:
java
python
php
javascript
julia
下面,读取文本文件的内容:
withopen('abc.txt','r')as f:
lines = LineWithHistory(f)for line in lines:print("Now the line is:", line)if'php'in line:for his in lines.history:print('HISTORY: line: {} content: {}'.format(his[0], his[1]))if'julia'in line:
lines.clear()print(len(lines.history))
我们逐行扫描文件的内容,并在当前行内容是php的时候,打印历史记录的内容
在当内容是julia时,清空所有的历史记录
这样,我们不仅迭代了生成器中的元素,还额外存储了一些与之相关的状态可供访问
4.7 对迭代器做切片操作
一般的迭代器不可作切片处理:
>>> a =[1,2,3,4]>>> b =iter(a)>>> b[1:]
Traceback (most recent call last):
File "<stdin>", line 1,in<module>
TypeError:'list_iterator'objectisnot subscriptable
可以用itertools.islice(Iterable, start, stop, step):
from itertools import islice
a =[1,2,3,4,5,6]for i in islice(a,2,4):print(i)
from itertools import zip_longest
first_name =['三','四','五']
last_name =['张','李','王','陈']for f, l in zip_longest(first_name, last_name, fillvalue='无名'):print(l, f)
结果:
张 三
李 四
王 五
陈 无名
使用dict(zip(a, b))可以产生一个字典
zip()可以接收多于2个序列作为参数
4.12 在不同的容器中迭代
如果希望迭代多个序列,并对他们中的每一个元素作同种操作
使用itertools.chain():
a =[1,2,3]
b ={'a','b','c'}for i in chain(a, b):print(i)