2012-02-21 5 views
5

Jak uzyskać wszystkie nazwy właściwości python class , w tym te właściwości odziedziczone po super klasach?Jak uzyskać dostęp do właściwości superklas Pythona, np. przez __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)] 

Jak mogę uzyskać dostęp do właściwości a via b? Potrzebujesz: "Podaj mi listę wszystkich nazw nazwisk od b włącznie z odziedziczonymi po!"

>>> [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] 
[] 

Chcę uzyskać wyniki od pierwszego (a), podczas pracy z drugim (b), ale bieżący tylko może uzyskać pustą listę. To również powinno działać dla drugiego C odziedziczone B.

+1

Zauważ, że 'y' nie jest właściwością , to tylko liczba całkowita. Czy chcesz mieć wszystkie zmienne klasy, które nie są funkcjami? –

+0

Zamiast "getX", miej 'get_x', jeśli interesujesz się stylem Python ([PEP 8] (http://www.python.org/dev/peps/pep-0008/)), lub jeśli nie masz t musi być w stanie wykonać wersję wywołania funkcji (będziesz, jeśli kiedykolwiek pójdziesz ustawiać właściwość przez 'super()' --- 'super (...). x = 'Y'' zawiedzie), po prostu użyj 'własność' jako dekorator, jako' @ właściwość', 'def x (self): return 'X''. –

+0

Dzięki za te komentarze. Próbowałem stworzyć prosty przykład zamiast mojego złożonego kodu i tak, w związku z tym nie myślałem o PEP8. Nie dbam o to "y", ponieważ potrzebuję tylko właściwości. – user1156548

Odpowiedz

3

Można użyć dir():

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

OK, myślę, że to działa dla mnie z 'print attr_name, attr .__ get __ (b)' na końcu. Dzięki. – user1156548

+0

Dzięki pomóc w #[email protected] za wskazówkę, prowadzącej do odpowiedzi alternatywna: 'dla c wb .__ klasy __.__ mro__: jeśli issubclass (C,) dla p w [ q dla q w c .__ dict __. items() if type (q [1]) == property]: print p [0], '=', p [1] .__ get __ (b) ' – user1156548

+0

@ user1156548: I nie myśl, że konieczne jest samodzielne chodzenie w MRO. Oczywiście, że * możesz *, ale dlaczego * powinien * ty? –

1

Można użyć „dir”, lub można śledzić wszystkie klasy, które są zawarte w krotce zwróconej przez „MRO” (metoda rozdzielczość rzędu, podana przez atrybut __mro__ w klasie) - to później metoda jest jedynym sposobem na odkrywanie atrybuty gdzie później nadpisane przez podklasy:

>>> 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) 
>>> 
Powiązane problemy