2011-02-03 10 views
8

hago a menudo esto cuando sustituir un método en una subclase:de acceso directo para super (tipo (auto), auto)

def method_x(self): 
    x = super(type(self), self).method_x() 

    [Some extra code] 
    return x 

Mi pregunta es: ¿Hay un atajo para super (tipo (auto) , yo)?

+14

Advertencia para cualquiera que lea esto: el código anterior es * incorrecto *. ¡No lo imites! –

+0

Glenn, Duncan: gracias por señalar que esto está mal. Tendré que grep mi código y cambiar esto. –

+0

@Glenn Maynard: No estoy seguro de entender por qué lo considera * incorrecto *. ¿Sería mejor usar 'super (self .__ class__, self)'? – martineau

Respuesta

17

No haga eso: si super podría simplemente usar como su primer argumento, entonces no se habría escrito para tomar dos argumentos en primer lugar. Debe pasar la clase real aquí no una expresión que podría cambiar si la clase ha sido subclasificada.

El primer argumento para super debe ser la clase que contiene la definición del método actual, ya que le está diciendo a super dónde en la lista de bases para comenzar su búsqueda.

Python 3 sabe esto y trata super() mágicamente en tiempo de compilación, pero en Python 2.x es solo una función normal, por lo que no tiene forma de averiguar esos parámetros por sí misma.

[Editar para agregar a mis puntos iniciales] En realidad, hay otra forma menos utilizada de usar super() en Python 2.x. Se puede utilizar un formulario independiente de super y tenerlo obligado cuando se accede a él:

>>> class A(object): 
    def foo(self): 
     print "A.foo" 


>>> class B(A): 
    def foo(self): 
     self.__super.foo() 
     print "B.foo" 


>>> B._B__super = super(B) 
>>> class C(A): 
    def foo(self): 
     self.__super.foo() 
     print "C.foo" 


>>> C._C__super = super(C) 
>>> class D(C,B): pass 

>>> D._D__super = super(D) 
>>> D().foo() 
A.foo 
B.foo 
C.foo 

No es una captura importante aquí: usted tiene que utilizar un nombre diferente para almacenar cada super objeto, que se puede hacer mediante el uso de self.__super, pero no puede crear un super sin encuadernar directamente en la definición de clase (porque no puede nombrar la clase si aún no existe) y si lo crea afuera tiene que ofuscar el nombre manualmente para asegurarse de establecer el correcto __super objeto para la clase. Para Python 2.6 y versiones posteriores probablemente puedas terminar esto como un decorador de clases.

+1

Recomendaría no recomendar esto; no es una gran ganancia para hacer algo tan inusual. –

+2

Sí, es complicado, por lo que probablemente sea menos utilizado, pero pensé que debería mencionarlo como una opción. Una opción mucho mejor, por supuesto, es simplemente usar Python 3.x (sujeto a que sea compatible con las bibliotecas que necesite) – Duncan

+0

Miré el uso de python3 en la actualidad. Estoy usando Pylons Pyramid, y algunas de sus dependencias aún no son compatibles con py3, así que tendré que volver a consultarlo dentro de unos meses. –