2012-02-21 12 views
5

¿Cómo puedo obtener todos los nombres de propiedad de una clase python incluyendo aquellas propiedades heredadas de las súper clases?Cómo acceder a las propiedades de las súper clases de Python, p. vía __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)] 

¿Cómo puedo acceder a las propiedades de a via b? Necesito: "Dame una lista de todos los propiedad nombres de b incluidos los heredados de un!"

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

Quiero obtener los resultados de la primera (a), cuando se trabaja con el segundo (B), pero la corriente sólo puede obtener una lista vacía. Esto también debería funcionar para otro heredado de C B.

+1

Tenga en cuenta que 'y' no es una propiedad , es solo un entero. ¿Desea que todas las variables de clase que no son funciones quizás? –

+0

En lugar de tener 'getX', tenga' get_x' si le importa el estilo de Python ([PEP 8] (http://www.python.org/dev/peps/pep-0008/)), o si no lo hace Necesito poder hacer la función llamada versión (lo harás si alguna vez vas configurando una propiedad a través de 'super()' --- 'super (...). x = 'Y'' fallará), solo usa 'property' como decorador, como' @ property', 'def x (self): return 'X''. –

+0

Gracias por esos comentarios. Intenté crear un ejemplo simple en lugar de mi código complejo y, sí, no pensé en PEP8. No me importa 'y' porque solo necesito las propiedades. – user1156548

Respuesta

3

Puede utilizar dir():

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

Ok, supongo que funciona para mí con un 'print attr_name, attr .__ get __ (b)' al final. Gracias. – user1156548

+0

Gracias a la ayuda en #[email protected] para una pista que conduce a una respuesta alternativa: 'por c en la clase de b __.__ mro__ .__: si issubclass (c, A): para p en [ q para q en c .__ dict __. items() if tipo (q [1]) == propiedad]: print p [0], '=', p [1] .__ get __ (b) ' – user1156548

+0

@ user1156548: I no piense que es necesario caminar el MRO usted mismo. Por supuesto que puede *, pero ¿por qué * debería * usted? –

1

Puede utilizar "dir", o usted puede seguir todas las clases que están contenidos en la tupla devuelta por (orden de resolución de métodos, dado por el atributo __mro__ en la clase) "MRO" - este último método es la única manera de descubrir los atributos que donde posteriormente anulado por las subclases:

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