2015-05-01 21 views
6

Chạy mã này:TypeError tài sản classmethod: 'sở hữu' đối tượng không Iterable

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 

tôi nhận được lỗi này:

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

tôi không thể tìm ra cách có một phương pháp học cư xử như một thuộc tính (không có dấu ngoặc đơn).

  • Bất cứ ai có thể giải thích cho tôi tại sao tôi gặp lỗi này?
  • Bất cứ ai có thể giải thích cho tôi cách tôi có thể có phương thức lớp học hoạt động như một tài sản không?

Trả lời

6

Dưới đây là một cách để sử dụng mô tả với một lớp:

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 

Tài liệu tham khảo:

+1

Tôi sẽ đi với nó vì nó trông tao nhã nhất với tôi. Cảm ơn rất nhiều! (PS Tôi không thể upvote vì tôi nhỏ hơn 15, xin lỗi vì điều này ...). – Narann

3

Thuộc tính luôn áp dụng cho các trường hợp, không phải lớp học.

Cách làm này sẽ được xác định một metaclass xác định tài sản trên phương pháp dụ riêng của mình, vì một lớp học là một thể hiện của metaclass của nó:

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

này hiện đang làm việc như mong đợi:

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

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

_Properties luôn áp dụng đối với trường hợp, không classes._ Cảm ơn tôi cũng vậy nhưng tôi không thể tìm thấy bất kỳ thông tin nào trong tài liệu chính thức. Bất kỳ nguồn nào cho điều này? – Narann

+0

Tôi không thể tìm thấy địa điểm chính xác ngay bây giờ, nhưng một nơi tuyệt vời để xem xét sẽ nằm trong [Hacker desectoror howto] của Raymond Hettinger (https://docs.python.org/2/howto/descriptor.html) trong tài liệu Python . Đó là giá trị đọc trong mọi trường hợp. –

+0

"Thuộc tính luôn áp dụng cho các phiên bản, không phải lớp học". Daniel Roseman với một số vàng! –

0

một giải pháp sẽ được, để sử dụng một WeakKeyDictionary, đó là iterable, giống như bạn muốn:

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

Về mặt kỹ thuật, nó có thể lặp lại, nhưng [như được ghi trong tài liệu] (https://docs.python.org/2/library/weakref.html#weakref.WeakKeyDictionary), bạn cần đảm bảo rằng không có phím nào biến mất trong khi bạn đang lặp lại nó. Điều đó có thể cực kỳ có vấn đề. – user2357112

+0

Chờ ... [source] (https://hg.python.org/cpython/file/2.7/Lib/weakref.py) thực sự có các bảo vệ cụ thể để ngăn không cho GC xóa các mục khỏi dict trong khi lặp lại là trong tiến trình, miễn là không có gì khác thay đổi dict. Tài liệu có thể cần cập nhật. – user2357112

Các vấn đề liên quan