iter()
提到iter(),可能你想到的就是传入一个iteratable对象作为参数,然后将其转换为一个iterator对象。但不得不提,iter()其实还可以接受两个参数。
iter(object[, sentinel])
- 当只有一个参数时:
object
必须是支持迭代协议(有__iter__()
方法)的集合对象;或必须支持序列协议(有__getitem__()
方法,且数字参数从 0 开始)。 - 当有两个参数时,那么
object
必须是可调用的对象,可以简单理解为传入一个函数。 这种情况下生成的迭代器,每次迭代调用它的__next__()
方法时都会不带实参地调用 object;如果返回的结果是sentinel
则触发 StopIteration,否则返回调用结果。
import random
from collections import Iterator
def get_number():
"""随机生成1-10的整数"""
num=random.randint(1,5)
print(f"The random number is {num}")
return num
random_number=iter(get_number,5)
#检测是否为Iterator
print(isinstance(random_number,Iterator))
for i in random_number:
print(f"get number: {i}")
可以看到,iter(object[, sentinel])
返回一个iterator对象。每次迭代时,都会调用get_number()函数,生成一个随机数。当迭代过程中生成5时, 与sentinel
相匹配,触发 StopIteration,停止迭代。
应用
构建块读取器
例如,从二进制数据库文件中读取固定宽度的块,直至到达文件的末尾:
from functools import partial
with open('mydata.db', 'rb') as f:
for block in iter(partial(f.read, 64), b''):
process_block(block)
文本解析
列如,解析字符串中的文本构成。
import re
from collections import namedtuple
NAME = r'(?P<NAME>[a-zA-Z_][a-zA-Z_0-9]*)'
NUM = r'(?P<NUM>\d+)'
PLUS = r'(?P<PLUS>\+)'
TIMES = r'(?P<TIMES>\*)'
EQ = r'(?P<EQ>=)'
WS = r'(?P<WS>\s+)'
master_pat = re.compile('|'.join([NAME, NUM, PLUS, TIMES, EQ, WS]))
def generate_tokens(pat, text):
Token= namedtuple('Token',['type','value'])
scanner= pat.scanner(text)
for m in iter(scanner.match, None):
yield Token(m.lastgroup, m.group())
for tok in generate_tokens(master_pat, 'foo = 23 + 42 * 10'):
print(tok)