2012-08-04 12 views
5

¿Hay buena (conveniente para usar en proyectos reales) formas o reducir repetitivo en cosas como esta¿Cómo evitar la repetición cuando se usa super (...) en Python 2.6+?

class B(A): 
    def qqq(self): # 1 unwanted token "self" 
     super(B, self).qqq() # 7 unwanted tokens plus 2 duplications ("B", "qqq") 
     do_something() 

quiero que se vea de la misma familia:

class B(A): 
    def qqq: 
     super 
     do_something() 

o (más realista)

class B(A): 
    @autosuper_before 
    def qqq(self): 
     do_something() 

¿Es posible en Python 2.6+ sin hackers abiertos?

@link super() in Python 2.x without args

+4

No tiene sentido luchar contra el parámetro 'self'. Explícito es mejor que implícito, los casos especiales no son lo suficientemente especiales como para romper las reglas, yadda yadda yadda. Además, ¿con qué frecuencia anulas un método sin parámetros y no haces nada antes de llamar a la siguiente implementación? – delnan

+0

¿Qué quiere decir con "hackers abiertos"? – BrenBarn

+0

@BrenBarn, "Hackes abiertos" aquí significa "El código se vuelve un poco más simple al precio de una desaceleración masiva o trazas desagradables desagradables o algo desagradable". –

Respuesta

4

tl; dr

Como dijo el PO "¿Es posible que en Python 2.6+ sin cortes abiertos?", La respuesta es: No se

Versión larga

Puede hacer un decorador simple que llame al ne xt padre con este método. El problema es que no tendrás control sobre los argumentos que quieres aprobar.

Editar: Esto no funcionará para una subclase que ya utilizan autosuper porque va eligió la clase equivocada y crea un bucle infinito.

def autosuper(fn): 
    def f(self, *args, **kw): 
     cl = super(type(self), self) 
     getattr(cl, fn.__name__)(*args, **kw) 
     return fn(self, *args, **kw) 
    return f 

¿Cómo puede hacerse esto? Python 3.x tiene una función super que no toma argumentos!

unfortunally, de super la 3.x Python es una clasey al mismo tiempo una palabra clave , porque sólo la presencia de su nombre va a cambiar el entorno actual para dar a conocer una variable llamada __class__ que es la derecha clase que necesitas usar!

Si marca el marco dentro de una función declarada en una clase, no hay ninguna variable __class__ y el atributo co_freevars del atributo f_code del marco está vacío. Cuando escriba el nombre super (no es necesario que lo llame), la cadena __class__ aparecerá en co_freevars, lo que significa que proviene de otro cierre. Además, si intenta acceder a la variable __class__ sin usar super, usará el bytecode LOAD_DEFER por este mismo motivo, en lugar de LOAD_GLOBAL, como sería normal con cada nombre indefinido.

Esto es tan loco que no se puede simplemente hacer hyper = super y llamar a este nuevo hyper variable sin argumentos (que es exactamente el mismo objeto que super).

Como no puedo competir con este gran parte de la magia negro en el interior del intérprete de Python, y porque el decorador autosuper no se declara dentro de una clase (para que no pueda acceder a la variable __class__ incluso si eso era posible en Python 2.x), no intentaré escribir un nuevo decorador y dejaré esta respuesta aquí como una advertencia para otras personas que quieran hacer eso.

Probablemente sea posible hacer algunos hackers para encontrar la clase correcta para usar, pero no voy a profundizar tanto. Consideraciones:

  • Cuando se aplica el decorador, la clase todavía no existe, por lo que esto debe hacerse cuando se llama a la función decorada.
  • La función que se está decorando todavía no es unbound method (que se eliminaron de Py3k) por lo que no puede verificar el atributo im_class.
  • El marco no parece contener ninguna información de la clase utilizada para hacer esta llamada (a menos que, por supuesto, no existe la variable __class__ y es posible obtener una referencia a la misma)
  • This answer proporcionada por OP también es bastante roto porque hace una gran cantidad de suposiciones malas y tiene problemas con las funciones decoradas.
+0

(me olvido de agregar "self" una y otra vez. (También me olvido de cambiar los argumentos o "super" en numerosos métodos cuando cambio el nombre de la clase o el nombre del método). –

+0

¿Debería funcionar razonablemente rápido? Se parece un poco al reflejo de Java, que se dice que es lento. ¿Puede el "reflejo" pasar de "f" (para mantenerlo liviano) a "autosuper" y dejar que "f" llame a algo ya preparado? (En realidad quiero algo así como las macros de Lisp que simplemente agregarán esa línea "super (...)" automáticamente) –

+0

@Vi. La reflexión de Java usa una sintaxis similar, pero es muy diferente de los decoradores. Simplemente agregará una llamada de función extra. Por cierto, cambié el código para usar la función 'super' en lugar de escribir mi propio – JBernardo

Cuestiones relacionadas