¿Por qué pycharm propone cambiar el método a estático?

154

La nueva versión de pycharm (3.1.3 edición comunitaria) propone convertir los métodos que no funcionan con el estado del objeto actual a estáticos.

ingrese la descripción de la imagen aquí

¿Cuál es la razón práctica para eso? ¿Algún tipo de optimización de micro-rendimiento (-o-memoria)?

zerkms
fuente
3
¿Hiciste clic en "más ..."? ¿Hace referencia a selfalgún lugar dentro del método? (Si la pregunta realmente es "¿por qué el diseño de los diseñadores de PyCharm esta manera ... vas a tener que pedirles, no tan ...)
Wooble
77
@Wooble: existe return 1una implementación de una sola línea del método. "Más" no contiene nada útil
zerkms

Respuestas:

189

PyCharm "piensa" que podría haber querido tener un método estático, pero olvidó declararlo como estático (usando el @staticmethoddecorador).

PyCharm propone esto porque el método no se usa self en su cuerpo y, por lo tanto, en realidad no cambia la instancia de la clase . Por lo tanto, el método podría ser estático, es decir, invocable sin pasar una instancia de clase o incluso sin haber creado una instancia de clase.

jolvi
fuente
44
Mucha gente ha respondido con esta respuesta de sabor. Sin embargo, agregaría que si sabe que definitivamente no va a ser un método estático, incluya un "throw NotImplementedError" mientras esté seguro de que no lo usará sin completarlo.
Richard Green
1
Puede haber casos en los que la advertencia de PyCharm no esté justificada porque no queremos un método estático ni cambiar el estado. Por otro lado, si el método aún no está implementado, siempre parece una buena idea plantear a NotImplementedError.
jolvi
3
Tengo el caso de que mi implementación predeterminada devuelve una constante, pero mis subclases pueden devolver un valor dependiendo de self. En este caso, la advertencia es descuidada y la marco con # noinspection PyMethodMayBeStatic. Es una pena que IntelliJ IDEA no ofrezca agregar este comentario de desactivación en los menús contextuales para esta advertencia.
Alfe
Sugiero cambiar la gravedad de esta inspección de PyCharm de "Advertencia" a "Sin resaltar, solo corregir" en las preferencias de PyCharm. (Está produciendo muchos falsos positivos para mí.)
maciek
51

De acuerdo con @jolvi, @ArundasR y otros, la advertencia ocurre en una función miembro que no se usa self.

Si está seguro de que PyCharm está equivocado, que la función no debería ser a @staticmethod, y si valora las advertencias cero, puede hacer que esta desaparezca de dos maneras diferentes:

Solución # 1

def bar(self):
    self.is_not_used()
    doing_something_without_self()

def is_not_used(self):
    pass

Solución # 2 [Gracias @ DavidPärsson ]

# noinspection PyMethodMayBeStatic
def bar(self):
    doing_something_without_self()

La aplicación que tenía para esto (la razón por la que no podía usar @staticmethod) estaba en hacer una tabla de funciones de controlador para responder a un campo de subtipo de protocolo. Todos los manejadores tenían que ser de la misma forma (estática o no estática). Pero algunos no hicieron nada con la instancia. Si hiciera esos estáticos, obtendría "TypeError: el objeto 'staticmethod' no es invocable".

Para respaldar la consternación del OP, sugerirle que agregue un método estático siempre que pueda, va en contra del principio de que es más fácil hacer que el código sea menos restrictivo más tarde que hacerlo más: hacer un método estático lo hace menos restrictivo ahora, ya que puede llame a class.f () en lugar de instancia.f ().

Adivina por qué existe esta advertencia:

  • Se anuncia métodoestático . Hace que los desarrolladores se den cuenta de algo que bien podrían haber pensado.
  • Como señala @ JohnWorrall, llama su atención cuando el self queda fuera de la función sin darse cuenta .
  • Es una señal para repensar el modelo de objetos; tal vez la función no pertenece a esta clase en absoluto.
Bob Stein
fuente
1
"hacer que un método sea estático lo hace menos restrictivo ahora" --- no lo hace en absoluto. Por ejemplo: métodos polimórficos
zerkms
Creo que el último punto vale la pena repetir: "¿por qué lo conviertes en un método, cuando es claramente una función?" Mantenga las cosas que realmente necesitan una instancia separadas de las cosas estructurales que se ocupan de algún aspecto. Luego puede subdividirlo fácilmente en un módulo separado.
dhill
@dhill Las reglas son cosas hermosas hasta el día en que piensas una excepción razonable. Describí uno, una lista de devoluciones de llamada.
Bob Stein
77
Agregar por # noinspection PyMethodMayBeStaticencima del método o la clase suprime la advertencia y, en mi opinión, es mejor que llamar a un método vacío.
David Pärsson
1
@Talha: selfno se elimina en Python3 en absoluto.
Junuxx
12

Creo que el motivo de esta advertencia es config en Pycharm. Puede desmarcar la selección El método puede ser estático en Editor-> Inspección

mincom
fuente
12
Mi pregunta era por qué existe tal inspección. Entiendo que puedo apagarlo. Lo siento, no es una respuesta.
zerkms
9

Estoy de acuerdo con las respuestas dadas aquí (el método no se usa selfy, por lo tanto, podría decorarse con @staticmethod).

Me gustaría agregar que tal vez desee mover el método a una función de nivel superior en lugar de un método estático dentro de una clase. Para obtener detalles, consulte esta pregunta y la respuesta aceptada: python: ¿debo usar métodos estáticos o funciones de nivel superior?

Mover el método a una función de nivel superior también reparará la advertencia de PyCharm.

tlo
fuente
Respuesta realmente útil: quizás PyCharm debería cambiar el nombre de la advertencia a 'el método puede ser estático o función de nivel superior'. Al refactorizar un método, pycharm creará una función de nivel superior y no un método estático de todos modos, si selfno es un parámetro.
Suzana
@tlo +1 por mencionar el decorador. Tengo una clase con un método que no utiliza selfy, por lo tanto, podría ser de nivel superior, sin embargo, esto no se siente lógico cuando se mira lo que hace este método: como nivel superior, se vería más como un método global, mientras que es de hecho, un pequeño método auxiliar para instancias creadas a partir de esa clase. Entonces, para mantener mi código lógicamente organizado, el decorador es la solución perfecta.
kasimir
7

Puedo imaginar las siguientes ventajas de tener un método de clase definido como estático:

  • puede llamar al método simplemente usando el nombre de la clase, no es necesario instanciarlo.

Las ventajas restantes son probablemente marginales si están presentes:

  • podría correr un poco más rápido
  • ahorra un poco de memoria
Jan Vlcinsky
fuente
Sí. Pero la cosa es que no lo estoy usando como método estático. De lo contrario, ya sería estático. Entonces PyCharm aconseja hacerlo sin una buena razón (?). "las ventajas restantes son probablemente marginales si están presentes" --- sí, exactamente. Pero si es el caso, es un consejo tonto de PyCharm
zerkms
1
@zerkms así es como sucede con algunas instancias encantadoras :-)
Jan Vlcinsky
2
Los métodos estáticos son enemigos de construir un buen software. Anulan muchos principios, por lo que el bitfuncionamiento más rápido no es el punto (porque se ejecutan en RAM, por lo que es rápido en ambos casos) y, como saben, las computadoras ahora tienen bunchmemoria, por lo que ya no es un problema. También tenga en cuenta su primer pensamiento: es un comportamiento procesal, no orientado a objetos.
AmirHossein
4

Como no se refirió selfen el barcuerpo del método, PyCharm pregunta si es posible que haya querido hacer barestática. En otros lenguajes de programación, como Java, existen razones obvias para declarar un método estático. En Python, el único beneficio real de un método estático (AFIK) es poder llamarlo sin una instancia de la clase. Sin embargo, si esa es su única razón, probablemente sea mejor usar una función de nivel superior, como se indica aquí .

En resumen, no estoy cien por ciento seguro de por qué está allí. Supongo que probablemente lo eliminarán en un próximo lanzamiento.

Don
fuente
3

Este mensaje de error me ayudó mucho, ya que no me había dado cuenta de que había escrito accidentalmente mi función usando mi reproductor de ejemplo de prueba

my_player.attributes[item] 

en lugar de la forma correcta

self.attributes[item]
John Worrall
fuente
1

Puede ser un poco complicado, pero a veces simplemente no necesita acceder self, pero preferiría mantener el método en la clase y no hacerlo estático. O simplemente desea evitar agregar un montón de decoradores antiestéticos. Aquí hay algunas posibles soluciones para esa situación.

Si su método solo tiene efectos secundarios y no le importa lo que devuelve:

def bar(self):
    doing_something_without_self()
    return self

Si necesita el valor de retorno:

def bar(self):
    result = doing_something_without_self()
    if self:
        return result

¡Ahora su método está usando selfy la advertencia desaparece!

Junuxx
fuente
0

La razón por la cual Pycharm lo hace como una advertencia porque Python se pasará a sí mismo como el primer argumento al llamar a un método no estático (no agregue @staticmethod). Pycharm lo sabe.

Ejemplo:

class T:
    def test():
        print "i am a normal method!"

t = T()
t.test()
output:
Traceback (most recent call last):
  File "F:/Workspace/test_script/test.py", line 28, in <module>
    T().test()
TypeError: test() takes no arguments (1 given)

Soy de Java, en Java "self" se llama "this", no necesita escribir self (o this) como argumento en el método de clase. Puedes llamarte a ti mismo como lo necesites dentro del método. Pero Python "tiene que" pasar a sí mismo como un argumento de método.

Al comprender esto, no necesita ninguna solución alternativa como respuesta de @BobStein.

Junyu Wu
fuente
Pasa selfy qué?
zerkms
@zerkms '@staticmethod' no pasa 'self'
Junyu Wu
Te acabo de citar: "Python pasará a sí mismo como el primer argumento ... Pycharm lo sabe". ¿Y qué? Pycharm lo sabe, yo lo sé. ¿Cuál es la razón para marcar el método?
zerkms
@zerkms porque Pycharm cree que su primer método param puede no ser el "self". Normalmente ppl no diseñará un parámetro de método y nunca lo usará. Pycharm cree que está creando un método estático y no se dio cuenta de que el primer parámetro no es el "yo", por lo que pone una advertencia por defecto. Esta confusión causada por el diseño del lenguaje de programación. Le sugiero que siga el diseño de programación (aunque parezca que no es un buen patrón), agregue "método estático" para evitar confusiones. Está totalmente bien si agregas un "self" y nunca lo uses si lo prefieres. Lo que digo es solo una opción diferente al comprender el diseño de programación.
Junyu Wu