簡體   English   中英

python:生成器對象上的屬性

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM