2015-05-01 73 views
6

運行此代碼:類方法屬性類型錯誤:「財產」對象不是可迭代

import weakref 

class A(object): 
    _instances = [] 
    def __init__(self): 
     self._instances.append(weakref.ref(self)) 

    @property 
    @classmethod 
    def instances(cls): 
     for inst_ref in cls._instances: 
      inst = inst_ref() 
      if inst is not None: 
       yield inst 

foo = A() 
bar = A() 
for inst in A.instances: 
    print inst 

我得到這個錯誤:

Traceback (most recent call last): 
    File "test.py", line 18, in <module> 
    for inst in A.instances: 
TypeError: 'property' object is not iterable 

如何有一個類的方法表現得像我想不出屬性(不包括括號)。

  • 任何人都可以解釋爲什麼我得到這個錯誤嗎?
  • 任何人都可以解釋我怎麼能有一個類方法行爲像一個屬性?

回答

6

下面是使用描述了一類的一種方法:

import weakref 

class classproperty(object): 
    def __init__(self, fget): 
     self.fget = fget 
    def __get__(self, owner_self, owner_cls): 
     return self.fget(owner_cls) 

class A(object): 
    _instances = [] 
    def __init__(self): 
     self._instances.append(weakref.ref(self)) 

    @classproperty 
    def instances(cls): 
     for inst_ref in cls._instances: 
      inst = inst_ref() 
      if inst is not None: 
       yield inst 

foo = A() 
bar = A() 
for inst in A.instances: 
    print inst 

參考文獻:

+1

我會隨身攜帶,因爲它看起來對我來說最爲優雅。非常感謝! (PS我不能高調,因爲我不到15歲,對此抱歉...)。 – Narann

3

屬性總是適用於實例,而不是類。

要做到這一點是定義一個元類,它定義了自己的實例方法的財產,因爲一類是它的元類的實例的方法:

class AMeta(type): 
    def __init__(self,name,bases,dict): 
     self._instances = [] 

    @property 
    def instances(self): 
     for inst_ref in self._instances: 
      inst = inst_ref() 
      if inst is not None: 
       yield inst 

class A(object): 
    __metaclass__ = AMeta 

    def __init__(self): 
     self._instances.append(weakref.ref(self)) 

這現在可以按預期:

>>> foo=A() 
>>> bar = A() 

>>> for inst in A.instances: 
...  print inst 
<__main__.A object at 0x1065d7290> 
<__main__.A object at 0x1065d7990> 
+0

_properties總是適用於實例,而不是classes._謝謝很多我雖然也是,但我無法在官方文檔中找到任何信息。任何來源? – Narann

+0

我現在找不到確切的地方,但在Python文檔中,Raymond Hettinger的[描述符howto](https://docs.python.org/2/howto/descriptor.html)是一個很好的地方。 。任何情況下都值得一讀。 –

+0

「屬性總是適用於實例,而不適用於類。」丹尼爾羅斯曼帶一些黃金! –

0

一個解決辦法是,使用WeakKeyDictionary,就像你想要的是可迭代的,:

import weakref 

class A(object): 
    instances = weakref.WeakKeyDictionary() 
    def __init__(self): 
     self.instances[self] = True 

foo = A() 
bar = A() 
for inst in A.instances: 
    print inst 
+0

它在技術上是可迭代的,但[如文檔中所述](https://docs.python.org/2/library/weakref.html#weakref.WeakKeyDictionary),您需要確保沒有任何按鍵消失正在迭代它。這可能是非常有問題的。 – user2357112

+0

等待... [源](https://hg.python.org/cpython/file/2.7/Lib/weakref.py)實際上有特定的警衛,以防止GC從迭代中刪除詞典中的條目在進行中,只要沒有其他修改字典。文檔可能需要更新。 – user2357112

相關問題