[英]python: attributes on a generator object
是否可以在生成器對象上創建屬性?
這是一個非常簡單的例子:
def filter(x):
for line in myContent:
if line == x:
yield x
現在說我有很多這些過濾器生成器對象浮動...也許其中一些是匿名的...我想稍后再回來詢問他們正在過濾的內容。 有沒有辦法我可以a)詢問生成器對象的x值或b)設置一個值為x的屬性,我以后可以詢問?
謝謝
是。
class Filter( object ):
def __init__( self, content ):
self.content = content
def __call__( self, someParam ):
self.someParam = someParam
for line in self.content:
if line == someParam:
yield line
不幸的是,生成器對象(調用生成器函數返回的結果)不支持添加任意屬性。 可以通過使用外部字典由發電機對象索引解決它在一定程度上,因為這樣的對象是可用作為鍵成一個字典。 那么,你想這樣做,說:
a = filter(23)
b = filter(45)
...
a.foo = 67
...
x = random.choice([a,b])
if hasattr(x, 'foo'): munge(x.foo)
你可以這樣做:
foos = dict()
a = filter(23)
b = filter(45)
...
foos[a] = 67
...
x = random.choice([a,b])
if x in foos: munge(foos[x])
對於任何愛好者來說,使用類而不是生成器(畢竟,類的一個或多個方法可以是生成器)。
如果您想查詢它們以進行調試,那么以下函數將有所幫助:
import inspect
def inspect_generator(g):
sourcecode = open(g.gi_code.co_filename).readlines()
gline = g.gi_code.co_firstlineno
generator_code = inspect.getblock(sourcecode[gline-1:])
output = "Generator %r from %r\n" % (g.gi_code.co_name, g.gi_code.co_filename)
output += "".join("%4s: %s" % (idx+gline, line) for idx, line in enumerate(generator_code))
output += "Local variables:\n"
output += "".join("%s = %r\n" % (key,value) for key,value in g.gi_frame.f_locals.items())
return output
print inspect_generator(filter(6))
"""Output:
Generator 'filter' from 'generator_introspection.py'
1: def filter(x):
2: for line in myContent:
3: if line == x:
4: yield x
Local variables:
x = 6
"""
如果您想詢問它們以實現功能,那么實現迭代器協議的類可能是更好的主意。
不可以。您無法在生成器上設置任意屬性。
由於·洛指出,你可以有一個對象, 看起來像一台發電機,並就像一台發電機。 如果它看起來像一只鴨子,就像一只鴨子,那么你就已經掌握了鴨子打字的定義。
但是,如果沒有適當的代理方法,它將不支持像gi_frame
這樣的生成器屬性。
我意識到這是一個非常遲來的答案,但......
您的代碼可以稍后只檢查生成器的變量,而不是存儲並稍后讀取一些其他屬性,使用:
filter.gi_frame.f_locals
我想Ants Aasma暗示了這一點。
關於這個問題的思考, 存在具有發電機周圍的一組屬性進行的一種方式。 這有點瘋狂 - 我強烈推薦Alex Martelli的建議而不是這個 - 但它在某些情況下可能會有用。
my_content = ['cat', 'dog days', 'catfish', 'dog', 'catalog']
def filter(x):
_query = 'I\'m looking for %r' % x
def _filter():
query = yield None
for line in my_content:
while query:
query = yield _query
if line.startswith(x):
query = yield line
while query:
query = yield _query
_f = _filter()
_f.next()
return _f
for d in filter('dog'):
print 'Found %s' % d
cats = filter('cat')
for c in cats:
looking = cats.send(True)
print 'Found %s (filter %r)' % (c, looking)
如果您想詢問生成器它的過濾內容,只需使用值為true的值調用send
。 當然,這段代碼可能太聰明了一半。 謹慎使用。
我剛剛在這里寫了一個裝飾器: http : //code.activestate.com/recipes/577057-generator-attributes/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.