2009-06-05 65 views
5

是否可以在生成器對象上創建屬性?python:生成器對象上的屬性

這裏是一個非常簡單的例子:

def filter(x): 
    for line in myContent: 
     if line == x: 
      yield x 

現在說我有很多這樣的濾波器產生物體漂浮......也許他們中的一些是匿名。我想以後回去審問他們爲他們過濾的東西。有沒有一種方法可以:a)詢問發生器對象的x值,或b)設置一個屬性值爲x,以後我可以查詢它?

謝謝

回答

6

不幸的是,發電機對象(從結果調用生成函數返回)不支持將任意的屬性。您可以通過使用由生成器對象索引的外部字典在某種程度上解決它,因爲這些對象可用作字典中的鍵。那麼,你最好喜歡做,說:

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]) 

對於任何愛好者,而不是使用一個發電機(一個或一個以上的類的類的畢竟,方法可以是生成器)。

16

是的。

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 
2

不可以。您不能在生成器上設置任意屬性。

由於·洛指出,你可以有一個對象,看起來像發電機,並行爲就像一臺發電機。如果它看起來像一隻鴨子,並且像一隻鴨子一樣行事,那麼你就有了鴨子打字的定義。

但是,如果沒有適當的代理方法,它將不支持像gi_frame這樣的生成器屬性。

0

關於這個問題的思考,讓發電機攜帶一組屬性的一種方法。這有點瘋狂 - 我強烈建議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) 

如果你要問什麼發電機它的過濾功能,只需撥打send與計算結果爲真的值。當然,這個代碼可能太聰明瞭一半。謹慎使用。

3

如果你想詢問他們進行調試,那麼下面的功能將幫助:

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 
""" 

如果你想詢問他們執行的功能則實現了迭代器協議類可能是一個更好的主意。

0

我意識到這是一個非常遲來的答案,但...

不是存儲後來讀了一些附加的屬性,你的代碼可能後來只是檢查發電機的變量(一個或多個),使用:

filter.gi_frame.f_locals

我想螞蟻Aasma暗示了這一點。

+0

我試過你的建議來檢查發生器的變量。它的工作原理是「StopIteration」尚未達到。之後,`gi_frame`變成`None`。 – bli 2017-02-03 16:14:13