2008-08-25 8 views
30

Si tengo código PythonPython clase super reflexión

class A(): 
    pass 
class B(): 
    pass 
class C(A, B): 
    pass 

y tengo clase C, hay una manera para recorrer es súper clasificada (A y B)? Algo así como pseudocódigo:

>>> magicGetSuperClasses(C) 
(<type 'A'>, <type 'B'>) 

Una solución parece ser inspect module y getclasstree función.

def magicGetSuperClasses(cls): 
    return [o[0] for o in inspect.getclasstree([cls]) if type(o[0]) == type] 

pero esta es una forma "Pythonian" de lograr el objetivo?

+2

El adjetivo correcto es "Pythonic". – asmeurer

+0

Ver también [Verificando si A es una superclase de B en Python] (/ q/1938755/1157100). –

Respuesta

36

C.__bases__ es una matriz de las clases súper, por lo que podría poner en práctica su hipotética función de este modo:

def magicGetSuperClasses(cls): 
    return cls.__bases__ 

pero me imagino que sería más fácil simplemente hacer referencia a cls.__bases__ directamente en la mayoría de los casos.

+0

Quisiera +1 esto si fuera corregido por cada punto de cdleary a continuación. –

11

@John: Su fragmento no funciona - está devolviendo la clase de las clases base (que también se conocen como metaclases). Lo que realmente quieres cls.__bases__:

class A: pass 
class B: pass 
class C(A, B): pass 

c = C() # Instance 

assert C.__bases__ == (A, B) # Works 
assert c.__class__.__bases__ == (A, B) # Works 

def magicGetSuperClasses(clz): 
    return tuple([base.__class__ for base in clz.__bases__]) 

assert magicGetSuperClasses(C) == (A, B) # Fails 

Además, si usted está usando Python 2.4+ puede utilizar generator expressions en lugar de crear una lista (a través de []), a continuación, convirtiéndolo en una tupla (a través de tuple). Por ejemplo:

def get_base_metaclasses(cls): 
    """Returns the metaclass of all the base classes of cls.""" 
    return tuple(base.__class__ for base in clz.__bases__) 

Es un ejemplo algo confuso, pero los genexps son generalmente fáciles y geniales. :)

+0

Parece que esta publicación ya no es relevante (John corrigió su respuesta). Si yo fuera tú, eliminaría esta publicación. –

4

El módulo de inspeccionar fue un buen comienzo, utilice la función getmro:

Return a tuple of class cls’s base classes, including cls, in method resolution order. No class appears more than once in this tuple. ...

>>> class A: pass 
>>> class B: pass 
>>> class C(A, B): pass 
>>> import inspect 
>>> inspect.getmro(C)[1:] 
(<class __main__.A at 0x8c59f2c>, <class __main__.B at 0x8c59f5c>) 

El primer elemento de la tupla devuelta es C, sólo se puede prescindir de ella.

2

si necesita saber para ordenar en qué super() llamaría a las clases puede usar C.__mro__ y no necesita inspect por lo tanto.

+0

Esto no funcionó para mí. En mi ejemplo, obtuve 'clase C (B): pase', y' C .__ mro__' resultados en 'AttributeError: class C no tiene atributo '__mro __'', mientras que 'inspect.getmro (C)' returns '(__main__ .C, __main __. B) '. Estoy usando Python 2.7.6. – m01

Cuestiones relacionadas