classmethod属性TypeError:“property”对象不是iterab

2024-04-27 19:21:56 发布

您现在位置:Python中文网/ 问答频道 /正文

运行此代码:

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

我搞不懂有一个类方法如何表现得像一个属性(没有括号)。

  • 有人能解释我为什么会犯这个错误吗?
  • 有谁能解释一下我如何让一个类方法表现得像一个属性吗?

Tags: instances方法inselfrefforobjectis
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>

下面是将描述符用于类的一种方法:

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

参考文献:

一种解决方案是,使用WeakKeyDictionary,这是iterable,就像您想要的那样:

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

相关问题 更多 >