@staticmethod vs @classmethod en Python

Tal vez un poco de código de ejemplo ayude. Observa la diferencia en las firmas de llamada de foo, class_foo y static_foo:

class A(object):
    def foo(self,x):
        print ("ejecutando foo(%s,%s)"%(self,x))

    @classmethod
    def class_foo(cls,x):
        print ("ejecutando class_foo(%s,%s)"%(cls,x))

    @staticmethod
    def static_foo(x):
        print ("ejecutando static_foo(%s)"%x)

a=A()

A continuación se muestra la forma habitual en que una instancia de objeto llama a un método. La instancia del objeto a se pasa implícitamente como primer argumento. Mientras que si llamamos al método directamente desde la clase, debemos pasarle el argumento.

a.foo(1)
# ejecutando foo(<__main__.A object at 0x7f39ff41e390>,1)

A.foo(2,1)
#ejecutando foo(2,1)

Con los métodos de clase (@classmethod), la clase de la instancia del objeto se pasa implícitamente como primer argumento en lugar de self.

a.class_foo(1)
# ejecutando class_foo(<class '__main__.A'>,1)

También puedes llamar a class_foo utilizando la clase. De hecho, si defines algo como un método de clase (@classmethod), probablemente es porque pretendes llamarlo desde la clase en lugar de desde una instancia de clase.

A.foo(1) habría producido un TypeError, pero A.class_foo(1) funciona perfectamente:

A.class_foo(1)
# ejecutando class_foo(<class '__main__.A'>,1)

Un uso que la gente ha encontrado para los métodos de clase es crear constructores alternativos heredables.

Con los métodos estáticos (@staticmethod), ni self (la instancia del objeto) ni cls (la clase) se pasan implícitamente como primer argumento. Se comportan como funciones simples, excepto que puedes llamarlas desde una instancia o desde la clase:

a.static_foo(1)
# ejecutando static_foo(1)

A.static_foo('Hola')
# ejecutando static_foo(Hola)

Los métodos estáticos se utilizan para agrupar funciones que tienen alguna conexión lógica con una clase.

Fuente: Stack Overflow