前段时间偶然发现了github上有了SCIP in python的翻译版本, 想起来之前还有最后一章没整明白就去看了一波, 收获很大, 在这整理一下
迭代器
作为类的迭代器
在python中,迭代器应该有一个更广泛的定义
在书的例子中给了一个典型的迭代器
class Letters(object):
def __init__(self):
self.current = 'a'
def __next__(self):
print("__next__called")
if self.current > 'd':
raise StopIteration #可选项
result = self.current
self.current = chr(ord(result)+1)
return result
def __iter__(self):
print("__iter__called")
return self
- 特征: 有 next, __iter__方法的类
- 迭代器被for循环调用时, 会调用__iter__, 之后循环调用__next__
2.1 此特性意味着可以在__iter__中重置迭代器的状态, 不用每次迭代都要使用新的迭代器
yield
- 需要区别可迭代对象与迭代器
3.1 如list, tuple等可迭代对象, 其特征是拥有__iter__方法, 没有__next__
3.2 在__iter__中有yield产出的类也可以作为视为迭代器
3.2.1 yield与__next__的return相当?
3.2.2 如下的类也可以作为迭代对象
# can only run once
def all_pairs(s):
for item1 in s:
for item2 in s:
yield (item1, item2)
class LetterIterable(object):
def __iter__(self):
current = 'a'
while current <= 'd':
yield current
current = chr(ord(current)+1)
协程(coroutine)
一个典型的协程示例
函数默认有__next__方法, 调用__next__时其将调用自身并使成为一个协程
def match(pattern):
print('Looking for ' + pattern)
try:
while True:
s = (yield)
if pattern in s:
print(s)
except GeneratorExit:
print("=== Done ===")
对其性质进行测试
f = match('xx')
f('xxyxx') #error
f.__next__()
f.send('xxbxx') #printed
f.send('xbxbx') #no result
f.send('xxbxx') #printed
f.close()
“生产、过滤和消耗”
producer: 使用send生产数据, 一般就是个生成器
filter:使用(yield)消耗数据, 并用send生产数据
filter本意即为过滤元素, 当然也可以对其进行转化
consumer:使用(yield)消耗数据
为了直观理解, 加入一个用例
def consumer():
print('ready to print')
try:
while True:
line = (yield)
print(line + '\t-faustellar')
except GeneratorExit:
print("=== Done ===")
def filter1(next_couroutine, param=None):
print('miao started')
try:
while True:
s = (yield)
if 'import' in s
s.replace('import', '加载')
next_couroutine.send(s)
except GeneratorExit:
print("=== miao Done ===")
next_coroutine.close()
def producer(fname, next_coroutine):
a = open(fname,encoding='utf-8')
for line in a:
next_coroutine.send(a)
定义完之后进行声明与组装, 注意顺序
step3 = consumer()
step3.__next__()
step2 = filter1(step3)
step2.__next__()
producer('runok.py',step2)
step2.close()
step3.close()
应用场景分析
在用例中, 协程并没有必要, 其就是以下代码的复杂版本:
a = open('runok.py',encoding='utf-8')
for line in a:
if 'import' in line
line.replace('import', '加载')
print(line + '\t-faustellar')
结合书中案例, 其将在诸多方面有极大应用:
- 但在更复杂的场景中, 这种模块化的方法将大大简化代码复用的难度
- 需要通信协作的场合
- 在一些需要mainloop的场合简化(?), 如摄像头, 直播/视频流, 实时行情分析等
之后将在深度学习中试用.0.