interacción super () y @staticmethod

¿Super () no está destinado a ser utilizado con métodos estáticos?

Cuando bash algo como

class First(object): @staticmethod def getlist(): return ['first'] class Second(First): @staticmethod def getlist(): l = super(Second).getlist() l.append('second') return l a = Second.getlist() print a 

Obtuve el siguiente error

 Traceback (most recent call last): File "asdf.py", line 13, in  a = Second.getlist() File "asdf.py", line 9, in getlist l = super(Second).getlist() AttributeError: 'super' object has no attribute 'getlist' 

Si cambio los métodos estáticos a métodos de clase y paso la instancia de la clase a super (), las cosas funcionan bien. ¿Estoy llamando super (tipo) incorrectamente aquí o hay algo que me estoy perdiendo?

La respuesta corta a

¿Estoy llamando super (tipo) incorrectamente aquí o hay algo que me estoy perdiendo?

es: sí, lo estás llamando incorrectamente … Y (de hecho, porque ) hay algo que te estás perdiendo.

Pero no te sientas mal; Este es un tema extremadamente difícil.

La documentación señala que

Si se omite el segundo argumento, el objeto super devuelto es independiente.

El caso de uso para los super objetos no unidos es extremadamente estrecho y raro. Vea estos artículos de Michele Simionato para su discusión sobre super() :

  • Cosas que debe saber sobre Python Super [1 de 3]
  • Cosas que debe saber sobre Python Super [2 de 3] (este cubre específicamente el super ilimitado)
  • Cosas que debe saber sobre Python Super [3 de 3]

Además, argumenta fuertemente por eliminar el super sin unir de Python 3 aquí .

Dije que lo estabas llamando “incorrectamente” (aunque la corrección no tiene sentido en gran medida sin contexto, y un ejemplo de juguete no da mucho contexto). Debido a que el super ilimitado es tan raro, y posiblemente simplemente injustificado, como sostiene Simionato, la forma “correcta” de usar super() es proporcionar el segundo argumento.

En su caso, la forma más sencilla de hacer que su ejemplo funcione es

 class First(object): @staticmethod def getlist(): return ['first'] class Second(First): @staticmethod def getlist(): l = super(Second, Second).getlist() # note the 2nd argument l.append('second') return l a = Second.getlist() print a 

Si crees que parece gracioso de esa manera, no te equivocas. Pero creo que lo que la mayoría de la gente espera cuando ve super(X) (o espera que cuando lo prueben en su propio código) es lo que Python te da si haces super(X, X) .

Cuando llama a un método normal en una instancia de objeto, el método recibe la instancia de objeto como primer parámetro. Puede obtener la clase del objeto hte y su clase primaria, por lo que tiene sentido llamar super .

Cuando llama a un método classmethod en una instancia de objeto o en una clase, el método recibe la clase como primer parámetro. Puede obtener la clase padre, por lo que tiene sentido llamar super .

Pero cuando llama a un método de método estático, el método no recibe nada, y no tiene forma de saber de qué objeto o clase fue llamado. Esa es la razón por la que no puedes acceder a super en un método estático.