Pourquoi pycharm propose-t-il de changer de méthode en statique

154

La nouvelle version de pycharm (édition communautaire 3.1.3) propose de convertir les méthodes qui ne fonctionnent pas avec l'état actuel de l'objet en statique.

entrez la description de l'image ici

Quelle en est la raison pratique? Une sorte d'optimisation des micro-performances (-ou-mémoire)?

zerkms
la source
3
Avez-vous cliqué sur "plus ..."? Faites-vous référence selfn'importe où dans la méthode? (Si la question est vraiment "pourquoi les concepteurs de PyCharm l'ont-ils conçu de cette façon ... vous devrez leur demander, pas SO ...)
Wooble
7
@Wooble: il n'y a return 1qu'une seule ligne d'implémentation de la méthode. "Plus" ne contient rien d'utile
zerkms

Réponses:

190

PyCharm "pense" que vous auriez peut-être voulu avoir une méthode statique, mais vous avez oublié de la déclarer statique (en utilisant le @staticmethoddécorateur).

PyCharm propose cela parce que la méthode n'utilise self dans son corps et donc ne pas vraiment changer l'instance de classe . La méthode peut donc être statique, c'est-à-dire appelable sans passer une instance de classe ou sans même avoir créé une instance de classe.

jolvi
la source
4
Tant de gens ont répondu avec cette réponse de saveur. J'ajouterais cependant, si vous savez que ce ne sera certainement pas une méthode statique, alors incluez un "throw NotImplementedError" pendant que vous êtes là pour être certain de ne pas l'utiliser sans le compléter.
Richard Green
1
Il peut y avoir des cas où l'avertissement de PyCharm est injustifié dans la mesure où nous ne voulons ni d'une méthode statique, ni de changer l'état. En revanche, si la méthode n'est pas encore implémentée, il semble toujours judicieux de lever un fichier NotImplementedError.
jolvi
3
J'ai le cas où mon implémentation par défaut renvoie une constante, mais mes sous-classes sont autorisées à renvoyer une valeur en fonction de self. Dans ce cas, l'avertissement est négligeable et je le marque avec # noinspection PyMethodMayBeStatic. C'est dommage qu'IntelliJ IDEA ne propose pas d'ajouter ce commentaire de désactivation dans les menus contextuels de cet avertissement.
Alfe
Je suggère de changer la gravité de cette inspection PyCharm de "Avertissement" à "Pas de mise en évidence, seulement corriger" dans les préférences de PyCharm. (Cela produit beaucoup de faux positifs pour moi.)
maciek
51

En accord avec @jolvi, @ArundasR et d'autres, l'avertissement se produit sur une fonction membre qui n'utilise pas self.

Si vous êtes sûr que PyCharm est erroné, que la fonction ne doit pas être a @staticmethod, et si vous n'évaluez aucun avertissement, vous pouvez faire disparaître celui-ci de deux manières différentes:

Solution de contournement n ° 1

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

def is_not_used(self):
    pass

Solution de contournement n ° 2 [Merci @ DavidPärsson ]

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

L'application que j'avais pour cela (la raison pour laquelle je ne pouvais pas utiliser @staticmethod) consistait à créer une table de fonctions de gestionnaire pour répondre à un champ de sous-type de protocole. Tous les gestionnaires devaient bien sûr être de la même forme (statique ou non statique). Mais certains n'ont rien fait avec l'instance. Si je les rendais statiques, j'obtiendrais "TypeError: l'objet 'staticmethod' n'est pas appelable".

À l'appui de la consternation de l'OP, suggérer d'ajouter une méthode statique chaque fois que vous le pouvez, va à l'encontre du principe selon lequel il est plus facile de rendre le code moins restrictif plus tard que de le rendre plus - rendre une méthode statique la rend moins restrictive maintenant, en ce sens que vous pouvez appelez class.f () au lieu de instance.f ().

Devinez pourquoi cet avertissement existe:

  • Il annonce une méthode statique . Cela rend les développeurs conscients de quelque chose qu'ils ont peut-être voulu.
  • Comme le souligne @ JohnWorrall, cela attire votre attention lorsque le soi a été exclu par inadvertance de la fonction.
  • C'est un signal pour repenser le modèle objet; peut - être que la fonction n'appartient pas du tout à cette classe.
Bob Stein
la source
1
«rendre une méthode statique la rend moins restrictive maintenant» - ce n'est pas du tout le cas. Ex: méthodes polymorphes
zerkms
Je pense que le dernier point mérite d'être répété: "pourquoi en faites-vous une méthode, alors que c'est clairement une fonction?" Gardez les éléments qui ont vraiment besoin d'une instance séparés des éléments structurels qui traitent de certains aspects. Vous pouvez ensuite facilement le subdiviser en module séparé.
dhill
Les règles @dhill sont de belles choses jusqu'au jour où vous imaginez une exception raisonnable. J'en ai décrit un, une liste de rappels.
Bob Stein
7
L'ajout # noinspection PyMethodMayBeStaticau-dessus de la méthode ou de la classe supprime l'avertissement, et est à mon avis mieux que d'appeler une méthode vide.
David Pärsson
1
@Talha: selfn'est pas du tout supprimé dans Python3.
Junuxx
12

Je pense que la raison de cet avertissement est la configuration dans Pycharm. Vous pouvez décocher la sélection La méthode peut être statique dans Editeur-> Inspection

mincom
la source
12
Ma question était de savoir pourquoi une telle inspection existe même. Je comprends que je peux l'éteindre. Désolé, pas de réponse.
zerkms
9

Je suis d'accord avec les réponses données ici (méthode n'utilise pas selfet pourrait donc être décorée avec @staticmethod).

J'aimerais ajouter que vous souhaitez peut-être déplacer la méthode vers une fonction de niveau supérieur au lieu d'une méthode statique à l'intérieur d'une classe. Pour plus de détails, consultez cette question et la réponse acceptée: python - dois-je utiliser des méthodes statiques ou des fonctions de niveau supérieur

Déplacer la méthode vers une fonction de niveau supérieur corrigera également l'avertissement PyCharm.

tlo
la source
Réponse vraiment utile - peut-être que PyCharm devrait renommer l'avertissement en «la méthode peut être une fonction statique ou de niveau supérieur». Lors de la refactorisation d'une méthode, pycharm créera de toute façon une fonction de niveau supérieur et non une méthode statique, si ce selfn'est pas un paramètre.
Suzana
@tlo +1 pour avoir mentionné le décorateur. J'ai une classe avec une méthode qui n'utilise pas selfet qui pourrait donc être de premier niveau, cependant, cela ne semble pas logique quand on regarde ce que fait cette méthode - en tant que niveau supérieur, elle ressemblerait davantage à une méthode globale, alors qu'elle est en fait une petite méthode d'assistance pour les instances créées à partir de cette classe. Donc, pour garder mon code organisé de manière logique, le décorateur est la solution parfaite.
kasimir
7

Je peux imaginer les avantages suivants d'avoir une méthode de classe définie comme statique:

  • vous pouvez appeler la méthode en utilisant simplement le nom de la classe, pas besoin de l'instancier.

les avantages restants sont probablement marginaux, voire présents:

  • pourrait fonctionner un peu plus vite
  • économiser un peu de mémoire
Jan Vlcinsky
la source
Oui. Mais le fait est que je ne l'utilise pas comme une méthode statique. Sinon, ce serait déjà statique. Donc PyCharm conseille de le faire sans raison (?). "les avantages restants sont probablement marginaux, voire pas du tout" --- oui, exactement. Mais si c'est le cas - c'est un conseil idiot de PyCharm
zerkms
1
@zerkms voici comment ça se passe avec quelques exemples charmants :-)
Jan Vlcinsky
2
Les méthodes statiques sont un ennemi à la construction de bons logiciels. Ils annulent de nombreux principes, donc bitcourir plus vite n'est pas le point (car ils fonctionnent en RAM, donc c'est rapide dans les deux cas) et comme vous le savez, les ordinateurs ont maintenant bunchde la mémoire, ce n'est donc plus un problème. Notez également votre première pensée: c'est un comportement procédural et non orienté objet.
AmirHossein
4

Puisque vous n'avez pas fait référence selfdans le barcorps de la méthode, PyCharm vous demande si vous auriez pu vouloir rendre barstatique. Dans d'autres langages de programmation, comme Java, il y a des raisons évidentes de déclarer une méthode statique. En Python, le seul réel avantage d'une méthode statique (AFIK) est de pouvoir l'appeler sans instance de la classe. Cependant, si c'est votre seule raison, il vaut probablement mieux utiliser une fonction de haut niveau - comme indiqué ici .

En bref, je ne sais pas à cent pour cent pourquoi c'est là. Je suppose qu'ils le supprimeront probablement dans une prochaine version.

Don
la source
3

Ce message d'erreur m'a aidé beaucoup, car je n'avais pas réalisé que j'avais accidentellement écrit ma fonction en utilisant mon lecteur d'exemple de test

my_player.attributes[item] 

au lieu de la bonne manière

self.attributes[item]
John Worrall
la source
1

Cela peut être un peu compliqué, mais parfois vous n'avez tout simplement pas besoin d'y accéder self, mais vous préféreriez garder la méthode dans la classe et ne pas la rendre statique. Ou vous voulez simplement éviter d'ajouter un tas de décorateurs disgracieux. Voici quelques solutions de contournement potentielles pour cette situation.

Si votre méthode n'a que des effets secondaires et que vous ne vous souciez pas de ce qu'elle renvoie:

def bar(self):
    doing_something_without_self()
    return self

Si vous avez besoin de la valeur de retour:

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

Maintenant, votre méthode utilise selfet l'avertissement disparaît!

Junuxx
la source
0

La raison pour laquelle Pycharm en fait un avertissement parce que Python passera self comme premier argument lors de l'appel d'une méthode non statique (sans ajouter @staticmethod). Pycharm le sait.

Exemple:

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)

Je viens de Java, en Java "self" s'appelle "this", vous n'avez pas besoin d'écrire self (ou this) comme argument dans la méthode de classe. Vous pouvez simplement vous appeler selon vos besoins dans la méthode. Mais Python "doit" passer soi-même comme argument de méthode.

En comprenant cela, vous n'avez besoin d'aucune solution de contournement en tant que réponse @BobStein.

Junyu Wu
la source
Ça passe selfalors quoi?
zerkms
@zerkms '@staticmethod' ne passe pas 'self'
Junyu Wu
Je viens de vous citer: "Python passera soi-même comme premier argument ... Pycharm le sait.". Et alors? Pycharm le sait, je le sais. Quelle est la raison de marquer la méthode?
zerkms du
@zerkms parce que Pycharm pense que votre premier paramètre de méthode n'est peut-être pas le "self". Normalement, ppl ne concevra pas de paramètre de méthode et ne l'utilisera jamais. Pycharm pense que vous créez une méthode statique et n'a pas réalisé que le premier paramètre n'est pas le "self", donc il met un avertissement par défaut. Cette confusion causée par la conception du langage de programmation. Je vous suggère de suivre la conception de la programmation (même si cela ne semble pas un bon modèle), ajoutez "staticmethod", pour éviter toute confusion. C'est tout à fait correct si vous ajoutez un "soi", ne l'utilisez jamais si vous préférez. Ce que je dis est juste une autre option en comprenant la conception de la programmation.
Junyu Wu le