2012-02-21 31 views
5

Làm thế nào tôi có thể nhận được tất cả các tên thuộc tính của một lớp python bao gồm các thuộc tính được thừa hưởng từ các lớp siêu?Cách truy cập các thuộc tính của các lớp siêu Python, ví dụ: qua __class __.__ dict__?

class A(object): 
    def getX(self): 
    return "X" 
    x = property(getX) 

a = A() 
a.x 
'X' 

class B(A): 
    y = 10 

b = B() 
b.x 
'X' 

a.__class__.__dict__.items() 
[('__module__', '__main__'), ('getX', <function getX at 0xf05500>), ('__dict__', <attribute '__dict__' of 'A' objects>), ('x', <property object at 0x114bba8>), ('__weakref__', <attribute '__weakref__' of 'A' objects>), ('__doc__', None)] 
b.__class__.__dict__.items() 
[('y', 10), ('__module__', '__main__'), ('__doc__', None)] 

Tôi làm cách nào để truy cập các thuộc tính của qua b? Cần: "Hãy cho tôi một danh sách tất cả các tài sản tên từ b bao gồm cả những tên được kế thừa từ một!"

>>> [q for q in a.__class__.__dict__.items() if type(q[1]) == property] 
[('x', <property object at 0x114bba8>)] 
>>> [q for q in b.__class__.__dict__.items() if type(q[1]) == property] 
[] 

Tôi muốn nhận kết quả từ (a) đầu tiên, khi làm việc với (b) thứ hai, nhưng hiện tại chỉ có thể nhận danh sách trống. Điều này cũng nên làm việc cho một C được thừa kế từ B.

+1

Lưu ý rằng 'y' không phải là một tài sản , nó chỉ là một số nguyên. Bạn có muốn tất cả các biến lớp không phải là hàm không? –

+0

Thay vì có 'getX', có' get_x' nếu bạn quan tâm đến kiểu Python ([PEP 8] (http://www.python.org/dev/peps/pep-0008/)), hoặc nếu bạn không ' t cần để có thể làm phiên bản gọi hàm (bạn sẽ nếu bạn đã bao giờ thiết lập một thuộc tính thông qua 'super()' --- 'super (...). x = 'Y'' sẽ thất bại), chỉ cần sử dụng 'property' như một trang trí, như' @ property', 'def x (self): return 'X''. –

+0

Cảm ơn những nhận xét đó. Tôi đã cố gắng để tạo ra một ví dụ đơn giản thay vì mã phức tạp của tôi và có, tôi do đó không nghĩ về PEP8. Tôi không quan tâm về điều đó vì tôi chỉ cần các thuộc tính. – user1156548

Trả lời

3

Bạn có thể sử dụng dir():

for attr_name in dir(B): 
    attr = getattr(B, attr_name) 
    if isinstance(attr, property): 
     print attr 
+0

Ok, tôi đoán vậy làm việc cho tôi với 'print attr_name, attr .__ get __ (b)' ở cuối. Cảm ơn. – user1156548

+0

Nhờ trợ giúp trên #[email protected] để biết gợi ý dẫn đến câu trả lời thay thế: 'cho c trong b .__ class __.__ mro__: nếu issubclass (c, A): cho p in [ q cho q trong c .__ dict __. items() nếu loại (q [1]) == thuộc tính]: in p [0], '=', p [1] .__ nhận __ (b) ' – user1156548

+0

@ user1156548: I không nghĩ rằng nó là cần thiết để đi bộ MRO chính mình. Tất nhiên bạn * có thể *, nhưng tại sao * nên * bạn? –

1

Bạn có thể sử dụng "dir", hoặc bạn có thể làm theo tất cả các lớp được chứa trong các tuple trả về bởi "MRO" (theo thứ tự độ phân giải phương pháp, được đưa ra bởi __mro__ thuộc tính trên lớp) - phương pháp sau đây là cách duy nhất phát hiện ra thuộc tính nơi sau overriden bởi lớp con:

>>> class A(object): 
... b = 0 
... 
>>> class B(A): 
... b = 1 
... 
>>> for cls in B.__mro__: 
...  for item in cls.__dict__.items(): 
...   if item[0][:2] != "__": 
...   print cls.__name__, item 
... 
B ('b', 1) 
A ('b', 0) 
>>> 
Các vấn đề liên quan