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 can't figure out how having a class method behave like a property (no parentheses).
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
References:
Properties always apply to instances, not classes.
The way to do this would be to define a metaclass that defines the property on its own instance method, since a 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))
This now works as expected:
>>> foo=A()
>>> bar = A()
>>> for inst in A.instances:
... print inst
<__main__.A object at 0x1065d7290>
<__main__.A object at 0x1065d7990>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With