Property classmethod TypeError: object 'property' is not iterable

Running this code:

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 

I get this error:

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

I cannot understand how a class method behaves like a property (without parentheses).

  • Can someone explain to me why I get this error?
  • Can someone explain to me how I could use a class method similar to a property?
+7
python
source share
3 answers

Here is one way to use descriptors with a class:

 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 

Literature:

+6
source share

Properties always apply to instances, not classes.

A way to do this would be to define a metaclass that defines the property on its own instance method, since the class is an instance of its metaclass:

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

Now this works as expected:

 >>> foo=A() >>> bar = A() >>> for inst in A.instances: ... print inst <__main__.A object at 0x1065d7290> <__main__.A object at 0x1065d7990> 
+4
source share

One solution would be to use WeakKeyDictionary , which is WeakKeyDictionary as you want:

 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
source share

All Articles