《Python Cookbook 3rd》笔记(4.6):带有外部状态的生成器函数
帶有外部狀態(tài)的生成器函數(shù)
問(wèn)題
你想定義一個(gè)生成器函數(shù),但是它會(huì)調(diào)用某個(gè)你想暴露給用戶(hù)使用的外部狀態(tài)值。
解法
如果你想讓你的生成器暴露外部狀態(tài)給用戶(hù),別忘了你可以簡(jiǎn)單的將它實(shí)現(xiàn)為一個(gè)類(lèi),然后把生成器函數(shù)放到 iter () 方法中過(guò)去。比如:
from collections import dequeclass linehistory:def __init__(self, lines, histlen=3):self.lines = linesself.history = deque(maxlen=histlen)def __iter__(self):for lineno, line in enumerate(self.lines, 1):self.history.append((lineno, line))yield linedef clear(self):self.history.clear()為了使用這個(gè)類(lèi),你可以將它當(dāng)做是一個(gè)普通的生成器函數(shù)。然而,由于可以創(chuàng)建一個(gè)實(shí)例對(duì)象,于是你可以訪問(wèn)內(nèi)部屬性值,比如 history 屬性或者是 clear() 方法。代碼示例如下:
with open('somefile.txt') as f:lines = linehistory(f)for line in lines:if 'python' in line:for lineno, hline in lines.history:print('{}:{}'.format(lineno, hline), end='')討論
關(guān)于生成器,很容易掉進(jìn)函數(shù)無(wú)所不能的陷阱。如果生成器函數(shù)需要跟你的程序其他部分打交道的話 (比如暴露屬性值,允許通過(guò)方法調(diào)用來(lái)控制等等),可能會(huì)導(dǎo)致你的代碼異常的復(fù)雜。如果是這種情況的話,可以考慮使用上面介紹的定義類(lèi)的方式。在__iter__() 方法中定義你的生成器不會(huì)改變你任何的算法邏輯。由于它是類(lèi)的一部分,所以允許你定義各種屬性和方法來(lái)供用戶(hù)使用。
一個(gè)需要注意的小地方是,如果你在迭代操作時(shí)不使用 for 循環(huán)語(yǔ)句,那么你得先調(diào)用 iter() 函數(shù)。比如:
>>> f = open('somefile.txt') >>> lines = linehistory(f) >>> next(lines) Traceback (most recent call last):File "<stdin>", line 1, in <module> TypeError: 'linehistory' object is not an iterator>>> # Call iter() first, then start iterating >>> it = iter(lines) >>> next(it) 'hello world\n' >>> next(it) 'this is a test\n' >>>總結(jié)
以上是生活随笔為你收集整理的《Python Cookbook 3rd》笔记(4.6):带有外部状态的生成器函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: 矩阵论-集合与映射,线性空间及其性质
 - 下一篇: 推荐算法--时效性(05)