@staticmethod vs @classmethod en Python

8 minutos de lectura

Avatar de usuario de Daryl Spitzer
daryl spitzer

¿Cuál es la diferencia entre un método decorado con @staticmethod y uno decorado con @classmethod?

  • Los métodos estáticos a veces son mejores como funciones de nivel de módulo en python por el bien de la limpieza. Con una función de módulo, es más fácil importar solo la función que necesita y evitar “.” innecesarios. sintaxis (te estoy mirando Objective-C). Los métodos de clase tienen más uso ya que se pueden usar en combinación con polimorfismo para crear funciones de “patrón de fábrica”. esto se debe a que los métodos de clase reciben la clase como un parámetro implícito.

    – Puño de la furia

    6 de diciembre de 2017 a las 3:44

  • tl; dr >> en comparación con los métodos normales, los métodos estáticos y los métodos de clase también se pueden acceder usando la clase, pero a diferencia de los métodos de clase, los métodos estáticos son inmutables a través de la herencia.

    – Sr. Posterior no normalizado

    11 de julio de 2018 a las 15:02


  • Charla relacionada de Raymond Hettinger sobre el tema: youtube.com/watch?v=HTLu2DFOdTg

    – mooooooooooooooooooooooo

    10 de septiembre de 2018 a las 9:35

Avatar de usuario de Thomas Wouters
Tomás Wouters

A método estático es un método que no sabe nada acerca de la clase o instancia a la que fue llamado. Solo obtiene los argumentos que se pasaron, sin un primer argumento implícito. Básicamente es inútil en Python: solo puede usar una función de módulo en lugar de un método estático.

A método de clase, por otro lado, es un método al que se le pasa la clase a la que se llamó, o la clase de la instancia a la que se llamó, como primer argumento. Esto es útil cuando desea que el método sea una fábrica para la clase: dado que obtiene la clase real a la que se invocó como primer argumento, siempre puede instanciar la clase correcta, incluso cuando hay subclases involucradas. Observa por ejemplo cómo dict.fromkeys()un método de clase, devuelve una instancia de la subclase cuando se llama a una subclase:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

  • Un método estático no es inútil: es una forma de colocar una función en una clase (porque lógicamente pertenece allí), al tiempo que indica que no requiere acceso a la clase.

    – Tony Mayer

    26 de septiembre de 2008 a las 10:10

  • Por lo tanto, solo ‘básicamente’ inútil. Dicha organización, así como la inyección de dependencias, son usos válidos de los métodos estáticos, pero dado que los módulos, no las clases como en Java, son los elementos básicos de la organización del código en Python, su uso y utilidad son raros.

    – Thomas Wouters

    26 de septiembre de 2008 a las 13:40

  • ¿Qué tiene de lógico definir un método dentro de una clase, cuando no tiene nada que ver ni con la clase ni con sus instancias?

    – Ben James

    12 de marzo de 2010 a las 9:11


  • ¿Quizás por el bien de la herencia? Los métodos estáticos se pueden heredar y anular al igual que los métodos de instancia y los métodos de clase y la búsqueda funciona como se esperaba (a diferencia de Java). Los métodos estáticos no se resuelven realmente de forma estática, ya sea que se llamen a la clase oa la instancia, por lo que la única diferencia entre la clase y los métodos estáticos es el primer argumento implícito.

    – haridsv

    8 de abril de 2010 a las 1:32

  • También crean un espacio de nombres más limpio y facilitan la comprensión de que la función tiene algo que ver con la clase.

    – Imbordar

    22 de agosto de 2011 a las 11:58

Avatar de usuario de Du D.
du d

Para decidir si usar @métodoestático o @métodoclase tienes que mirar dentro de tu método. Si su método accede a otras variables/métodos en su clase, use @classmethod. Por otro lado, si su método no toca ninguna otra parte de la clase, use @staticmethod.

class Apple:

    _counter = 0

    @staticmethod
    def about_apple():
        print('Apple is good for you.')

        # note you can still access other member of the class
        # but you have to use the class instance 
        # which is not very nice, because you have repeat yourself
        # 
        # For example:
        # @staticmethod
        #    print('Number of apples have been juiced: %s' % Apple._counter)
        #
        # @classmethod
        #    print('Number of apples have been juiced: %s' % cls._counter)
        #
        #    @classmethod is especially useful when you move your function to another class,
        #       you don't have to rename the referenced class 

    @classmethod
    def make_apple_juice(cls, number_of_apples):
        print('Making juice:')
        for i in range(number_of_apples):
            cls._juice_this(i)

    @classmethod
    def _juice_this(cls, apple):
        print('Juicing apple %d...' % apple)
        cls._counter += 1

  • ¿Cuál sería la ventaja de classmethod y cls._counter frente a staticmethod y Apple._counter?

    – Robert Nowak

    11 oct 2019 a las 10:38

  • cls._counter todavía sería cls._counter incluso si el código se coloca en una clase diferente o se cambia el nombre de la clase. Apple._counter es específico para el Apple clase; para una clase diferente, o cuando se cambia el nombre de la clase, deberá cambiar la clase a la que se hace referencia.

    – apaderno

    12 de noviembre de 2019 a las 22:55

  • Espero que con “mover” no te refieras a “copiar” jajaja

    – Zaquías

    23 de noviembre de 2022 a las 21:38

  • ¿Por qué molestarse con el decorador en ese caso? Su descripción realmente no aclara

    – Mehdi

    9 de marzo a las 14:02

avatar de usuario de me_and
yo y

Documentos oficiales de Python:

@métodoclase

Un método de clase recibe la clase como primer argumento implícito, al igual que un método de instancia recibe la instancia. Para declarar un método de clase, usa este modismo:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ... 

El @classmethod la forma es una funcion
decorador – consulte la descripción de las definiciones de funciones en Definiciones de funciones para detalles.

Se puede llamar en la clase (como C.f()) o en una instancia (como C().f()). La instancia se ignora excepto por su clase. Si se llama a un método de clase para una clase derivada, el objeto de la clase derivada se pasa como el primer argumento implícito.

Los métodos de clase son diferentes a los métodos estáticos de C++ o Java. Si quieres esos, mira staticmethod() en esta sección.

@métodoestático

Un método estático no recibe un primer argumento implícito. Para declarar un método estático, usa este modismo:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ... 

El @staticmethod la forma es una funcion
decorador – consulte la descripción de las definiciones de funciones en Definiciones de funciones para detalles.

Se puede llamar en la clase (como C.f()) o en una instancia (como C().f()). La instancia se ignora excepto por su clase.

Los métodos estáticos en Python son similares a los que se encuentran en Java o C++. Para un concepto más avanzado, véase
classmethod() en esta sección.

  • ¿Cuál sería la ventaja de classmethod y cls._counter frente a staticmethod y Apple._counter?

    – Robert Nowak

    11 oct 2019 a las 10:38

  • cls._counter todavía sería cls._counter incluso si el código se coloca en una clase diferente o se cambia el nombre de la clase. Apple._counter es específico para el Apple clase; para una clase diferente, o cuando se cambia el nombre de la clase, deberá cambiar la clase a la que se hace referencia.

    – apaderno

    12 de noviembre de 2019 a las 22:55

  • Espero que con “mover” no te refieras a “copiar” jajaja

    – Zaquías

    23 de noviembre de 2022 a las 21:38

  • ¿Por qué molestarse con el decorador en ese caso? Su descripción realmente no aclara

    – Mehdi

    9 de marzo a las 14:02

Avatar de usuario de la comunidad
Comunidad

Aquí es un breve artículo sobre esta cuestión

La función @staticmethod no es más que una función definida dentro de una clase. Es invocable sin instanciar la clase primero. Su definición es inmutable a través de la herencia.

La función @classmethod también se puede llamar sin instanciar la clase, pero su definición sigue a la Subclase, no a la clase Padre, a través de la herencia. Eso es porque el primer argumento para la función @classmethod siempre debe ser cls (clase).

  • Entonces, ¿eso significa que al usar un método estático siempre estoy vinculado a la clase principal y con el método de clase estoy vinculado a la clase en la que declaro el método de clase (en este caso, la subclase)?

    -Mohan Gulati

    3 de noviembre de 2009 a las 19:06

  • No. Al usar un método estático no estás obligado en absoluto; no hay un primer parámetro implícito. Al usar classmethod, obtiene como primer parámetro implícito la clase en la que llamó al método (si lo llamó directamente en una clase), o la clase de la instancia en la que llamó al método (si lo llamó en una instancia).

    –Matt Anderson

    3 de noviembre de 2009 a las 19:18

  • Podría expandirse un poco para mostrar que, al tener una clase como primer argumento, los métodos de clase tienen acceso directo a otros atributos y métodos de clase, mientras que los métodos estáticos no (necesitarían codificar MyClass.attr para eso)

    – Mestre León

    3 mayo 2012 a las 10:01


  • “Su definición es inmutable a través de la herencia”. no tiene ningún sentido en Python, puede anular un método estático muy bien.

    – cz

    17 sep 2019 a las 15:20

¿Ha sido útil esta solución?