2010-03-13 11 views
51

me encontré con error de método no unido en python con el código¿Cuál es la ventaja de usar métodos estáticos en Python?

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

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

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

Después de leer muchos mensajes útiles aquí, pensé cómo podría añadir @staticmethod Unidos para ver el código de trabajo. Soy principiante de pitón. ¿Puede alguien explicar por qué uno querría definir métodos estáticos? O bien, ¿por qué no todos los métodos se definen como métodos estáticos?

+1

Esta es una pregunta extraña. Los métodos estáticos son un diseño * necesario *. No es una cosa de "ventaja". Los usas porque debes. Es una característica de diseño de una clase tener métodos estáticos. ¿Estás preguntando qué métodos estáticos están en primer lugar? Creo que la pregunta podría volver a redactarse para definir más claramente lo que necesita saber. –

+9

No, no quería saber qué son. Lo que quería saber es por qué es una "necesidad", que se ha vuelto clara a partir de las respuestas dadas por otros. Es entonces cuando lo definirías en lugar de los métodos no estáticos. Gracias. – Curious2learn

Respuesta

61

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

De modo que no son útiles para los métodos diarios.

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

Se podrían colocar fuera de la clase, pero agrupándolos dentro la clase puede tener sentido donde solo son aplicables allí.

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

+0

Gracias. Esto aclara por qué cada método no debe ser un método estático. – Curious2learn

+2

@ Curious2learn: No * todos *, pero * algunos * métodos son útiles como métodos estáticos. Piensa en un ejemplo de clase 'Locale', cuyas instancias serán locales (duh). Un método 'getAvailableLocales()' sería un buen ejemplo de un método estático de dicha clase: pertenece claramente a la clase Locale, aunque claramente no pertenece a ninguna instancia particular. – MestreLion

+0

... y tampoco es un método de clase, ya que puede no necesitar acceder a ninguno de los métodos de las clases. – MestreLion

4

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

de Python tiene un gran documentación sobre los métodos estáticos aquí:
http://docs.python.org/library/functions.html#staticmethod

+0

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 de hacerlo? – Curious2learn

+4

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

+4

Ese argumento sería verdadero en Java, donde las funciones no pueden vivir por sí mismas, pero siempre se definen en el contexto de una clase. Pero en Python puede tener funciones y funciones de clase estáticas. 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. – extraneon

0

Los métodos estáticos no tienen casi ninguna razón-a-ser en Python. Utiliza métodos de instancia o métodos de clase.

def method(self, args): 
    self.member = something 

@classmethod 
def method(cls, args): 
    cls.member = something 

@staticmethod 
def method(args): 
    MyClass.member = something 
    # The above isn't really working 
    # if you have a subclass 
+0

Has dicho "casi". ¿Hay un lugar donde puedan ser mejores que las alternativas? – Javier

+0

@Javier: No puedo pensar en uno, pero probablemente haya uno, ¿por qué se incluiría ese método en la biblioteca de Python? –

+0

@Javier, @Georg: Tiene mucha fe de que el corpus de Python no tiene cruft. –

11

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

Supongamos que tenemos un llamado classMath continuación

nadie querrá crear el objeto de class Math
y luego invocar métodos como ceil y floor y fabs en él.

Así que los hacemos static.

Por ejemplo haciendo

>> Math.floor(3.14) 

es mucho mejor que

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

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

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

No tienen acceso a 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 todos los métodos estáticos.

+5

¿Pero por qué no un paquete de matemáticas? Python tiene paquetes para eso, no necesita una definición de clase para crear un espacio de nombres. – extraneon

+5

@extraneon: Sí, lo sé, pero quería algo simple y familiar para la explicación, así que usé 'Matemáticas'. Es por eso que capitalicé 'M'. –

+6

El OP no preguntó qué son los métodos estáticos. Él preguntó cuál era su ventaja. Usted está explicando cómo usarlos, no cómo son útiles. En su ejemplo particular, un espacio de nombres tendría mucho más sentido. – Javier

12

Cuando llama a un objeto de función desde una instancia de objeto, se convierte en un 'método vinculado' y obtiene que el objeto de instancia se pasa como primer argumento.

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

Cuando llama a un objeto staticmethod (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) 
+3

+1: Finalmente una gran explicación sobre qué métodos estáticos * y * son los métodos de clase. Aunque no explicó * por qué * alguna vez querría usar un método estático, al menos explicó claramente en un ejemplo simple qué ambos son * mucho * mejores que los documentos oficiales. – MestreLion

14

Esto no es tan al punto de su pregunta real, pero ya que ha dicho que es un novato de Python tal vez sea útil, y nadie más ha salido y lo dijo explícitamente.

Nunca hubiera arreglado el código anterior haciendo que el método sea un método estático. Yo tampoco he deshecho de la clase y acaba de escribir 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 agruparlos en un módulo - es decir, poner a todos en el mismo archivo, el nombre de sample.py ejemplo; entonces

import sample 

Choices=range(100) 
print sample.drawSample(5,Choices) 
yo hubiera añadido un método init de la clase y ha creado una instancia que tenía métodos útiles

O:

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) 

(que también cambió las convenciones de caso en el ejemplo anterior para que coincida 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 haya datos o estados que deberían asociarse con los métodos, para lo que son las clases. De lo contrario, puede usar funciones, que es para qué sirven las funciones.

+0

Gracias por el comentario. Necesité una clase en este caso porque quiero trabajar con la muestra extraída. No, no utilicé un método estático, pero quería aprender, ya que me encontré con el término cuando busqué información sobre el mensaje de error que recibí. Pero su consejo sobre cómo reunir las funciones en un módulo sin definir una clase sería útil para otras funciones que necesito. Así que gracias. – Curious2learn

+2

+1: Esa fue una buena explicación sobre algunos conceptos erróneos que tuvo el OP. Y usted fue muy honesto al decir, por adelantado, que usted * no * en realidad estaba respondiendo su pregunta acerca de los métodos estáticos, pero mejor dio una * solución * mucho mejor diciendo que su problema no requiere clases en absoluto. – MestreLion

83

Consulte this article para una explicación más detallada.

TL; DR

1.It elimina el uso de self argumento.

2.It reduce el uso de memoria porque Python no tiene que crear una instancia de un bound-method para cada objeto instiantiated:

>>>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.It mejora la legibilidad del código, lo que significa que el método no depende de la situación de la objeto en sí.

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

+2

¡Esta debería ser la respuesta más votada! ¡Gracias! –

+0

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

0

Debido namespacing funciones es agradable (como ya se ha señalado):

  1. Cuando quiero ser explícito acerca de los métodos que no cambian el estado del objeto, que utilizan métodos estáticos. Esto desalienta a las personas de mi equipo a comenzar a cambiar los atributos del objeto en esos métodos.

  2. Cuando refactorizo ​​el código realmente podrido, comienzo tratando de hacer tantos métodos @staticmethod como sea posible. Esto me permite luego extraer estos métodos en una clase, aunque estoy de acuerdo, esto rara vez es algo que utilizo, me sirvió algunas veces.

0

En mi punto de vista, no existe una única actuación ventaja de utilizar @staticmethod s en comparación con sólo la definición de la función fuera de y separado de la clase de otro modo sería un @staticmethod de.

Lo único que diría justifica su existencia es la conveniencia. Los métodos estáticos son comunes en otros lenguajes de programación populares, ¿por qué no python? Si desea crear una función con un comportamiento que esté estrechamente relacionado con la clase para la que la está creando, pero en realidad no accede ni modifica los datos internos de una instancia de la clase de una manera que justifique su conceptualización como una característica típica. El método de esa clase muestra un @staticmethod arriba y cualquiera que lea su código inmediatamente aprenderá mucho sobre la naturaleza del método y su relación con la clase.

Una cosa que de vez en cuando me gusta hacer es colocar la funcionalidad que mi clase utiliza internamente mucho en privado @staticmethod s. De esa forma no acumulo la API expuesta por mi módulo con métodos que nadie que use mi módulo necesitaría ver y mucho menos usar.

Cuestiones relacionadas