2009-04-11 33 views
14

Cho một lớp mà giữ một registry của các đối tượng của nó:iterating trên đối tượng thể hiện của một lớp học được đưa ra trong Python

class Person(object): 
    __registry = [] 

    def __init__(self, name): 
     self.__registry.append(self) 
     self.name = name 

Làm thế nào tôi có thể làm cho công việc mã sau (mà không sử dụng Person .__ registry):

for personobject in Person: 
    print personobject 

Trong khi nghiên cứu, tôi đã tìm thấy gợi ý mà một người có thể truy cập __metaclass__ với một phương thức __getitem__. Bất kỳ ý tưởng làm thế nào điều này sẽ như thế nào?

+0

ehh đừng làm một cái nhìn xấu xí trông khá. –

Trả lời

20

Bạn có thể làm cho đối tượng lớp học của bạn có thể lặp lại bằng metaclass đơn giản.

class IterRegistry(type): 
    def __iter__(cls): 
     return iter(cls._registry) 

class Person(object): 
    __metaclass__ = IterRegistry 
    _registry = [] 

    def __init__(self, name): 
     self._registry.append(self) 
     self.name = name 

(Tôi cũng đã thay đổi __registry để _registry để làm cho nó dễ dàng hơn để truy cập từ metaclass). Sau đó,

>>> p = Person('John') 
>>> p2 = Person('Mary') 
>>> for personobject in Person: 
...  print personobject 
... 
<person.Person object at 0x70410> 
<person.Person object at 0x70250> 
+0

cảm ơn bạn rất nhiều ... đó là chính xác những gì tôi đang tìm kiếm;) – Titusz

+0

Lời khuyên thực sự hay: Tôi không biết điều này :) – jkp

+0

Tại sao điều này không làm việc với chỉ cần đặt def __iter__ trong lớp Person? Chỉ cần tự hỏi. –

2

bạn có thể làm điều đó với:

for item in Person.__registry: 
    print(item) 
+0

thats rõ ràng ... nhưng tôi muốn làm cho nó hoạt động như: cho mục trong Classname ... (chỉ cho vẻ đẹp của nó ...) – Titusz

+0

bạn cần phải làm cho lớp học của bạn iterable sau đó, tôi đoán – SilentGhost

+0

và nó không btw đẹp, – SilentGhost

10

Thứ nhất, không sử dụng đôi __ tên. Chúng được dành riêng để sử dụng bởi Python. Nếu bạn muốn "riêng tư", hãy sử dụng đơn _.

Thứ hai, hãy giữ loại điều này đơn giản nhất có thể. Đừng lãng phí rất nhiều thời gian và năng lượng vào một cái gì đó phức tạp. Đây là một vấn đề đơn giản, giữ mã đơn giản nhất có thể để hoàn thành công việc.

class Person(object): 
    _registry = [] 

    def __init__(self, name): 
     self._registry.append(self) 
     self.name = name 

for p in Person._registry: 
    print p 
+0

Vấn đề là giải pháp _registry * là * cách đơn giản nhất có thể để làm điều này. Bất cứ điều gì khác chỉ là cố gắng "đặt son môi trên một con lợn". –

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