¿Cuál es el propósito de los métodos estáticos? ¿Cómo sé cuándo usar uno? [duplicate]

14 minutos de lectura

Avatar de usuario de Curious2learn
curioso2aprender

Me encontré con un error de método no enlazado en python con este código:

import random

class Sample(object):
    def drawSample(samplesize, List):
        sample = random.sample(List, samplesize)
        return sample

Choices=range(100)
print(Sample.drawSample(5, Choices))

Pude solucionar el problema agregando @staticmethod al método. Sin embargo, no entiendo muy bien la situación.

¿Cuál es el punto de usar métodos “estáticos”? ¿Por qué resuelve el problema en este código y por qué son necesarios? Por el contrario, ¿por qué alguna vez no quiere hacerlo (es decir, ¿por qué se necesita un código adicional para hacer que el método sea estático)?

  • No, no quería saber cuáles son. Lo que quería saber era por qué es una “necesidad”, que ha quedado claro a partir de las respuestas dadas por otros. Ahí es cuando lo definiría en lugar de los métodos no estáticos. Gracias.

    – Curioso2aprender

    15 de marzo de 2010 a las 0:41

  • @S.Lott: ¿Cuándo es necesario usar un método estático en lugar de usar un método de clase normal? Por lo que sé, un método de clase puede hacer todo lo que puede hacer un método estático. Staticmethod tiene “ventajas” como se enumeran en otra parte de esta publicación, pero no puedo ver ninguna razón por la que un método de clase no se pueda usar en ningún lugar donde se pueda usar un método estático, por lo que es una necesidad.

    – RFV

    21 de enero de 2019 a las 4:40


avatar de usuario de zanetu
zanetú

Ver Este artículo para una explicación detallada.

TL;DR

1. Elimina el uso de self argumento.

2. Reduce el uso de la memoria porque Python no tiene que instanciar un método vinculado para cada objeto instanciado:

>>>RandomClass().regular_method is RandomClass().regular_method
False
>>>RandomClass().static_method is RandomClass().static_method
True
>>>RandomClass.static_method is RandomClass().static_method
True

3. Mejora la legibilidad del código, lo que significa que el método no depende del estado del objeto en sí.

4. Permite la anulación de métodos en el sentido de que si el método se definiera a nivel de módulo (es decir, fuera de la clase), una subclase no podría anular ese método.

  • Esta debería ser la respuesta aceptada. El hecho de que el método estático en cualquier instancia y la clase en sí sean el mismo objeto es una ventaja real, especialmente cuando tiene muchas instancias (por ejemplo, cada instancia para un registro de base de datos mutable).

    – Zhuoyun Wei

    12 de febrero de 2018 a las 7:47

  • +1 y estoy de acuerdo con @ZhuoyunWei. Solo responda que explique las pocas razones por las que un método estático a veces es preferible a un método de clase (aunque 1 y 3 son realmente la misma razón).

    – Alex

    28 de mayo de 2018 a las 16:04

  • La mejor respuesta a “por qué método estático”, pero la pregunta original también preguntó “¿por qué no todos los métodos son estáticos?”. El corto “sin acceso a los atributos de la instancia” también cubriría eso.

    – Exú

    16 de septiembre de 2019 a las 7:25

  • En mi opinión, la única ventaja real es que puede anularlo en una subclase, pero incluso eso tiene la sensación de que está haciendo algo mal en cuanto a programación orientada a objetos, ¿en qué caso de uso haría eso?

    – Boris Churzin

    6 de julio de 2020 a las 18:45

  • 3. – si no hay un estado, entonces, ¿por qué crear una clase en primer lugar? las funciones del módulo serían igual de buenas, con menos código.

    – Alex

    9 de diciembre de 2020 a las 15:19

Avatar de usuario de Oddthinking
pensamiento extraño

Los métodos estáticos tienen un uso limitado, porque no tienen acceso a los atributos de una instancia de una clase (como lo hace un método regular) y no tienen acceso a los atributos de la clase en sí (como lo hace un método de clase). ).

Por lo tanto, no son útiles para los métodos cotidianos.

Sin embargo, pueden ser útiles para agrupar alguna función de utilidad junto con una clase, por ejemplo, una conversión simple de un tipo a otro, que no necesita acceso a ninguna información aparte de los parámetros proporcionados (y quizás algunos atributos globales del módulo. )

Podrían colocarse fuera de la clase, pero agruparlos dentro de la clase puede tener sentido cuando solo sean aplicables allí.

También puede hacer referencia al método a través de una instancia o la clase, en lugar del nombre del módulo, lo que puede ayudar al lector a comprender con qué instancia está relacionado el método.

  • @Curious2learn: No todospero alguno Los métodos son útiles como métodos estáticos. Piensa en un ejemplo Locale class, cuyas instancias serán locales (duh). A getAvailableLocales() El método sería un buen ejemplo de un método estático de tal clase: claramente pertenece a la clase Locale, mientras que también claramente no pertenece a ninguna instancia en particular.

    – Mestre León

    3 de mayo de 2012 a las 4:01

  • … y tampoco es un método de clase, ya que es posible que no necesite acceder a ninguno de los métodos de las clases.

    – Mestre León

    3 mayo 2012 a las 11:05

  • Un editor señala que un método estático puede acceder a los atributos de clase, navegando explícitamente hacia abajo desde el class_name.attributesimplemente no cls.attribute o self.attribute. Esto es cierto para los atributos “públicos”. Por convención, no debe acceder a atributos ocultos con un guión bajo, o nombres alterados con dos guiones bajos, de esta manera. También significa que su código será más frágil cuando los atributos cambien de lugar en la jerarquía de herencia.

    – Pensamiento extraño

    12 de septiembre de 2017 a las 23:19

  • Una cita de Guido que ayuda a decidir cuándo usar métodos estáticos (nunca): “Todos sabemos cuán limitados son los métodos estáticos. (Son básicamente un accidente, en los días de Python 2.2 cuando estaba inventando clases y descriptores de nuevo estilo , tenía la intención de implementar métodos de clase, pero al principio no los entendía y accidentalmente implementé métodos estáticos primero. Luego fue demasiado tarde para eliminarlos y solo proporcionar métodos de clase”.

    – Boris Churzin

    6 de julio de 2020 a las 18:40

  • @GuzmanOjero mail.python.org/pipermail/python-ideas/2012-May/014969.html

    – Boris Churzin

    4 de abril de 2022 a las 6:53

Avatar de usuario de Vicki Laidler
Vicki Laidler

Este no es el punto de su pregunta real, pero dado que ha dicho que es un novato en Python, tal vez sea útil, y nadie más lo ha dicho explícitamente.

Nunca habría arreglado el código anterior haciendo que el método fuera un método estático. Hubiera abandonado la clase y simplemente hubiera escrito una función:

def drawSample(samplesize,List):
    sample=random.sample(List,samplesize)
    return sample

Choices=range(100)
print drawSample(5,Choices)

Si tiene muchas funciones relacionadas, puede agruparlas en un módulo, es decir, ponerlas todas en el mismo archivo, llamado sample.py por ejemplo; después

import sample

Choices=range(100)
print sample.drawSample(5,Choices)

O hubiera agregado un __init__ método a la clase y creó una instancia que tenía métodos útiles:

class Sample(object):
'''This class defines various methods related to the sample'''

    def __init__(self, thelist):
        self.list = thelist

    def draw_sample(self, samplesize):
        sample=random.sample(self.list,samplesize)
        return sample

choices=Sample(range(100))
print choices.draw_sample(5)

(También cambié las convenciones de mayúsculas y minúsculas en el ejemplo anterior para que coincidan con el estilo recomendado por PEP 8).

Una de las ventajas de Python es que no te obliga a usar clases para todo. Puede usarlos solo cuando hay datos o estados que deben asociarse con los métodos, que es para lo que son las clases. De lo contrario, puede usar funciones, que es para lo que están las funciones.

  • Gracias por el comentario. Necesitaba una clase en este caso porque quiero trabajar con la muestra dibujada. No, no utilicé un método estático, pero quería aprender sobre él, ya que encontré el término al buscar información sobre el mensaje de error que recibí. Pero su consejo sobre la recopilación de funciones en un módulo sin definir una clase sería útil para otras funciones que necesito. Así que gracias.

    – Curioso2aprender

    15 de marzo de 2010 a las 0:46

  • +1: Esa fue una buena explicación sobre algunos conceptos erróneos que tenía el OP. Y fuiste muy honesto al decir, por adelantado, que estabas no en realidad respondiendo a su pregunta sobre métodos estáticos, pero más bien diste una respuesta mucho mejor solución diciendo que su problema no requiere clases en absoluto.

    – Mestre León

    3 de mayo de 2012 a las 4:19

Avatar de usuario de Pratik Deoghare
Deoghare Pratik

¿Por qué uno querría definir métodos estáticos??

Supongamos que tenemos un class llamó Math después

nadie querrá crear objeto de class Math

y luego invocar métodos como ceil y floor y fabs en eso.

Así que los hacemos static.

por ejemplo haciendo

>> Math.floor(3.14)

es mucho mejor que

>> mymath = Math()
>> mymath.floor(3.14)

Así que son útiles de alguna manera. No necesita crear una instancia de una clase para usarlos.

¿Por qué no todos los métodos se definen como métodos estáticos??

No tienen acceso a las variables de instancia.

class Foo(object):
    def __init__(self):
        self.bar="bar"

    def too(self):
        print self.bar

    @staticmethod
    def foo():
        print self.bar

Foo().too() # works
Foo.foo() # doesn't work

Es por eso que no hacemos que todos los métodos sean estáticos.

Avatar de usuario de Joooeey
Joooeeey

Las alternativas a un staticmethod están: classmethod, instancemethody function. Si no sabe cuáles son, desplácese hacia abajo hasta la última sección. si un staticmethod es mejor que cualquiera de estas alternativas, depende de para qué se escriba.

ventajas del método estático de Python

  • Si no necesita acceder a los atributos o métodos de la clase o instancia, un staticmethod es mejor que un classmethod o instancemethod. Así queda claro (desde el @staticmethod decorador) que el estado de la clase y la instancia no se lee ni modifica. Sin embargo, usando un function hace esa distinción aún más clara (ver desventajas).
  • La firma de llamada de un staticmethod es el mismo que el de un classmethod o instancemethoda saber <instance>.<method>(<arguments>). Por lo tanto, puede ser fácilmente reemplazado por uno de los Tres si eso es necesario más adelante o en una clase derivada. No puedes hacer eso con un simple function.
  • A staticmethod se puede utilizar en lugar de un function para dejar claro que pertenece subjetivamente a una clase y para evitar conflictos de espacio de nombres.

desventajas del método estático de Python

  • No puede acceder a atributos o métodos de la instancia o clase.
  • La firma de llamada de un staticmethod es el mismo que el de un classmethod o instancemethod. Esto enmascara el hecho de que el staticmethod en realidad no lee ni modifica la información de ningún objeto. Esto hace que el código sea más difícil de leer. ¿Por qué no usar simplemente un function?
  • A staticmethod es difícil de reutilizar si alguna vez necesita llamarlo desde fuera de la clase/instancia donde se definió. Si existe alguna posibilidad de reutilización, un function es la mejor opción.
  • Él staticmethod rara vez se usa, por lo que las personas que leen el código que incluye uno pueden tardar un poco más en leerlo.

alternativas a un método estático en Python

Para abordar discutir las ventajas de la staticmethodnecesitamos saber cuáles son las alternativas y en qué se diferencian entre sí.

  • Él staticmethod pertenece a una clase pero no puede acceder ni modificar ninguna instancia o información de clase.

Hay tres alternativas para ello:

  • Él classmethod tiene acceso a la clase de la persona que llama.
  • Él instancemethod tiene acceso a la instancia de la persona que llama y su clase.
  • Él function no tiene nada que ver con las clases. Es el más cercano en capacidad al staticmethod.

Así es como se ve esto en el código:

# function
# has nothing to do with a class
def make_cat_noise(asker_name):
    print('Hi %s, mieets mieets!' % asker_name)

# Yey, we can make cat noises before we've even defined what a cat is!
make_cat_noise('JOey')  # just a function

class Cat:
    number_of_legs = 4

    # special instance method __init__
    def __init__(self, name):
        self.name = name

    # instancemethod
    # the instance (e.g. Cat('Kitty')) is passed as the first method argument
    def tell_me_about_this_animal(self, asker_name):
        print('Hi %s, This cat has %d legs and is called %s'
              % (asker_name, self.number_of_legs, self.name))

    # classmethod
    # the class (e.g. Cat) is passed as the first method argument
    # by convention we call that argument cls
    @classmethod
    def tell_me_about_cats(cls, asker_name):
        print("Hi %s, cats have %d legs."
              % (asker_name, cls.number_of_legs))
        # cls.name  # AttributeError because only the instance has .name
        # self.name  # NameError because self isn't defined in this namespace

    # staticmethod
    # no information about the class or the instance is passed to the method
    @staticmethod
    def make_noise(asker_name):
        print('Hi %s, meooow!' % asker_name)
        # class and instance are not accessible from here

# one more time for fun!
make_cat_noise('JOey')  # just a function

# We just need the class to call a classmethod or staticmethod:
Cat.make_noise('JOey')  # staticmethod
Cat.tell_me_about_cats('JOey')  # classmethod
# Cat.tell_me_about_this_animal('JOey')  # instancemethod -> TypeError

# With an instance we can use instancemethod, classmethod or staticmethod
mycat = Cat('Kitty')  # mycat is an instance of the class Cat
mycat.make_noise('JOey')  # staticmethod
mycat.tell_me_about_cats('JOey')  # classmethod
mycat.tell_me_about_this_animal('JOey')  # instancemethod

Cuando llama a un objeto de función desde una instancia de objeto, se convierte en un ‘método enlazado’ y obtiene el objeto de instancia como primer argumento.

Cuando llamas a un classmethod object (que envuelve un objeto de función) en una instancia de objeto, la clase del objeto de instancia se pasa como primer argumento.

Cuando llamas a un staticmethod objeto (que envuelve un objeto de función), no se utiliza ningún primer argumento implícito.

class Foo(object):

    def bar(*args):
        print args

    @classmethod
    def baaz(*args):
        print args

    @staticmethod
    def quux(*args):
        print args

>>> foo = Foo()

>>> Foo.bar(1,2,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got int instance instead)
>>> Foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> Foo.quux(1,2,3)
(1, 2, 3)

>>> foo.bar(1,2,3)
(<Foo object at 0x1004a4510>, 1, 2, 3)
>>> foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> foo.quux(1,2,3)
(1, 2, 3)

Avatar de usuario de David Fox
david zorro

Los métodos estáticos son geniales porque no tienes que declarar una instancia del objeto al que pertenece el método.

El sitio de python tiene una excelente documentación sobre métodos estáticos aquí:
http://docs.python.org/library/functions.html#staticmethod

  • gracias david Pero, ¿por qué no definir cada método como un método estático, ya que también funcionan en instancias? ¿Hay algún inconveniente en hacerlo?

    – Curioso2aprender

    13 de marzo de 2010 a las 13:23

  • @Curious2learn: No, con métodos estáticos no tiene acceso a la instancia: La instancia se ignora excepto por su clase.

    – Félix Kling

    13 de marzo de 2010 a las 13:31


  • Ese argumento sería cierto en Java, donde las funciones no pueden vivir por sí mismas sino que siempre se definen en el contexto de una clase. Pero en Python puedes tener funciones y funciones de clase estática. Esta respuesta realmente no muestra por qué elegir un método estático en lugar de un método que no está en una clase.

    – extraneón

    13 de marzo de 2010 a las 13:54

  • @extraneon: eso es más una cuestión de preferencias organizativas del código; tener métodos estáticos le da a uno la opción adicional.

    – Charles Duffy

    13 de marzo de 2010 a las 15:18

  • @Félix – Gracias. Esto aclara por qué cada método no debe ser un método estático.

    – Curioso2aprender

    13 de marzo de 2010 a las 15:23

¿Ha sido útil esta solución?