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