Perché Pycharm propone di cambiare il metodo in statico


154

La nuova versione di Pycharm (3.1.3 community edition) propone di convertire i metodi che non funzionano con lo stato dell'oggetto corrente in statici.

inserisci qui la descrizione dell'immagine

Qual è la ragione pratica per questo? Qualche tipo di ottimizzazione delle micro-prestazioni (o memoria)?


3
Hai fatto clic su "altro ..."? Ti riferisci selfovunque all'interno del metodo? (Se la domanda è davvero "perché i designer di PyCharm l'hanno progettata in questo modo ... dovrai chiederglielo, non SO ...)
Wooble

7
@Wooble: esiste return 1un'implementazione a riga singola del metodo. "Altro" non contiene nulla di utile
zerkms,

Risposte:


189

PyCharm "pensa" che potresti aver voluto avere un metodo statico, ma hai dimenticato di dichiararlo statico (usando il @staticmethoddecoratore).

PyCharm lo propone perché il metodo non utilizza self nel suo corpo e quindi non modifica l'istanza della classe . Quindi il metodo potrebbe essere statico, ovvero richiamabile senza passare un'istanza di classe o senza aver nemmeno creato un'istanza di classe.


4
Così tante persone hanno risposto con questa risposta aromatica. Vorrei aggiungere però, se sai che sicuramente non sarà un metodo statico, includi un "lancio NotImplementedError" mentre sei lì per essere sicuro di non usarlo senza completarlo.
Richard Green

1
Potrebbero esserci casi in cui l'avvertimento di PyCharm è ingiustificato in quanto non vogliamo né un metodo statico né cambiare lo stato. D'altra parte, se il metodo non è ancora implementato, sembra sempre una buona idea sollevare a NotImplementedError.
jolvi,

3
Ho il caso che la mia implementazione predefinita restituisca una costante, ma le mie sottoclassi possono restituire un valore a seconda self. In questo caso l'avviso è trascurabile e lo segnalo con # noinspection PyMethodMayBeStatic. È un peccato che IntelliJ IDEA non offra l'aggiunta di questo commento disabilitante nei menu di scelta rapida per questo avviso.
Alfe,

Suggerisco di modificare la gravità di questa ispezione PyCharm da "Avvertenza" a "Nessuna evidenziazione, solo correzione" nelle preferenze di PyCharm. (Sta producendo molti falsi positivi per me.)
maciek

51

Concordato con @jolvi, @ArundasR e altri, l'avviso si verifica su una funzione membro che non utilizza self.

Se sei sicuro che PyCharm abbia torto, che la funzione non dovrebbe essere una @staticmethode se apprezzi zero avvisi, puoi farla sparire in due modi diversi:

Soluzione alternativa n. 1

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

def is_not_used(self):
    pass

Soluzione alternativa n. 2 [Grazie @ DavidPärsson ]

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

L'applicazione che avevo per questo (il motivo per cui non potevo usare @staticmethod) era nel creare una tabella di funzioni del gestore per rispondere a un campo del sottotipo di protocollo. Tutti i gestori dovevano avere la stessa forma di corso (statico o non statico). Ma alcuni non sono riusciti a fare nulla con l'istanza. Se li rendessi statici otterrei "TypeError: l'oggetto 'staticmethod' non è richiamabile".

A sostegno della costernazione del PO, suggerendo di aggiungere il metodo statico ogni volta che è possibile, va contro il principio che è più facile rendere il codice meno restrittivo in seguito, piuttosto che renderlo più - rendere un metodo statico lo rende ora meno restrittivo, in quanto è possibile chiama class.f () invece di instance.f ().

Indovina perché esiste questo avviso:

  • Si pubblicizza staticmethod . Rende gli sviluppatori consapevoli di qualcosa che potrebbero aver inteso.
  • Come sottolinea @ JohnWorrall, attira la tua attenzione quando il sé viene inavvertitamente lasciato fuori dalla funzione.
  • È un suggerimento ripensare il modello a oggetti; forse la funzione non appartiene affatto a questa classe.

1
"rendere statico un metodo ora lo rende meno restrittivo" --- non lo fa affatto. Ad esempio: metodi polimorfici
zerkms,

Penso che l'ultimo punto meriti di essere ripetuto: "perché lo rendi un metodo, quando è chiaramente una funzione?" Tieni le cose che hanno davvero bisogno di un'istanza separate dalle cose strutturali che trattano alcuni aspetti. È quindi possibile suddividerlo facilmente in un modulo separato.
discesa

Le regole di @dhill sono cose belle fino al giorno in cui pensi a un'eccezione ragionevole. Ne ho descritto uno, un elenco di callback.
Bob Stein,

7
Aggiungendo # noinspection PyMethodMayBeStaticsopra il metodo o la classe si sopprime l'avvertimento, ed è secondo me meglio che chiamare un metodo vuoto.
David Pärsson,

1
@Talha: selfnon viene affatto rimosso in Python3.
Junuxx,

12

Penso che il motivo di questo avvertimento sia la configurazione in Pycharm. È possibile deselezionare il metodo di selezione può essere statico in Editor-> Ispezione


12
La mia domanda era perché esiste ancora una simile ispezione. Capisco di poterlo spegnere. Spiacente, non una risposta.
zerkms,

9

Sono d'accordo con le risposte fornite qui (il metodo non utilizza selfe quindi potrebbe essere decorato @staticmethod).

Vorrei aggiungere che potresti voler spostare il metodo su una funzione di livello superiore anziché su un metodo statico all'interno di una classe. Per i dettagli vedere questa domanda e la risposta accettata: python - dovrei usare metodi statici o funzioni di alto livello

Spostare il metodo su una funzione di livello superiore risolverà anche l'avviso PyCharm.


Risposta davvero utile - forse PyCharm dovrebbe rinominare l'avvertimento in "il metodo può essere statico o di livello superiore". Quando si esegue il refactoring di un metodo, pycharm creerà comunque una funzione di livello superiore e non un metodo statico, se selfnon è un parametro.
Suzana,

@tlo +1 per menzionare il decoratore. Ho una classe con un metodo che non usa selfe quindi potrebbe essere di alto livello, tuttavia, questo non sembra logico se si guarda a cosa fa questo metodo - poiché di livello superiore sembrerebbe più un metodo globale, mentre è in effetti un piccolo metodo di supporto per le istanze create da quella classe. Quindi, per mantenere logicamente organizzato il mio codice, il decoratore è la soluzione perfetta.
Kasimir,

7

Posso immaginare i seguenti vantaggi di avere un metodo di classe definito come statico:

  • puoi chiamare il metodo semplicemente usando il nome della classe, senza bisogno di istanziarlo.

i vantaggi rimanenti sono probabilmente marginali se presenti:

  • potrebbe correre un po 'più veloce
  • salva un po 'di memoria

Sì. Ma il fatto è che non lo sto usando come metodo statico. Altrimenti sarebbe già statico. Quindi PyCharm consiglia di farlo senza una buona ragione (?). "i vantaggi rimanenti sono probabilmente marginali se presenti" --- sì, esattamente. Ma se è il caso - è un consiglio stupido di PyCharm
zerkms,

1
@zerkms ecco come vanno le cose in alcuni casi affascinanti :-)
Jan Vlcinsky,

2
I metodi statici sono nemici nella costruzione di un buon software. Annullano molti principi in modo che la bitcorsa più veloce non sia il punto (perché corrono in RAM quindi è veloce in entrambi i casi) e come sapete i computer ora hanno bunchmemoria, quindi non è più un problema. Nota anche il tuo primo pensiero: si tratta di un comportamento procedurale non orientato agli oggetti.
AmirHossein,

4

Dato che non hai fatto riferimento selfnel barcorpo del metodo, PyCharm sta chiedendo se avresti potuto voler rendere barstatico. In altri linguaggi di programmazione, come Java, ci sono ovvi motivi per dichiarare un metodo statico. In Python, l'unico vero vantaggio di un metodo statico (AFIK) è la possibilità di chiamarlo senza un'istanza della classe. Tuttavia, se questa è la tua unica ragione, probabilmente starai meglio con una funzione di alto livello, come nota qui .

In breve, non sono sicuro al cento per cento perché sia ​​lì. Immagino che probabilmente lo rimuoveranno in una prossima versione.


3

Questo messaggio di errore mi ha aiutato moltissimo, poiché non mi ero reso conto di aver scritto per errore la mia funzione usando il mio esempio di test player

my_player.attributes[item] 

invece del modo corretto

self.attributes[item]

1

Potrebbe essere un po 'disordinato, ma a volte non è necessario accedere self, ma preferiresti mantenere il metodo nella classe e non renderlo statico. Oppure vuoi solo evitare di aggiungere un mucchio di sgradevoli decoratori. Ecco alcune possibili soluzioni per quella situazione.

Se il tuo metodo ha solo effetti collaterali e non ti interessa cosa restituisce:

def bar(self):
    doing_something_without_self()
    return self

Se hai bisogno del valore restituito:

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

Ora il tuo metodo sta usando selfe l'avvertimento scompare!


0

Il motivo per cui Pycharm lo rende un avvertimento perché Python passerà da solo come primo argomento quando chiama un metodo none statico (non aggiungere @staticmethod). Pycharm lo sa.

Esempio:

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)

Vengo da Java, in Java "self" si chiama "this", non è necessario scrivere self (o this) come argomento nel metodo di classe. Puoi semplicemente chiamare self come ti serve all'interno del metodo. Ma Python "deve" passare sé come argomento del metodo.

Comprendendo questo non è necessario alcun trucco come risposta di @BobStein.


Passa e selfallora?
zerkms,

@zerkms '@staticmethod' non passa 'self'
Junyu Wu il

Ti ho appena citato: "Python passerà da solo come primo argomento ... Pycharm lo sa". E allora? Pycharm lo sa, lo so. Qual è il motivo per contrassegnare il metodo?
zerkms,

@zerkms perché Pycharm pensa che il tuo primo parametro di metodo potrebbe non essere il "sé". Normalmente ppl non progetta un parametro param e non lo usa mai. Pycharm pensa che tu stia creando un metodo statico e non ha realizzato che il primo parametro non è il "sé", quindi mette un avviso di default. Questa confusione causata dalla progettazione del linguaggio di programmazione. Ti suggerisco di seguire il progetto di programmazione (anche se non sembra un buon modello), aggiungere "metodo statico", per evitare confusione. Va benissimo se aggiungi un "io" e non lo usi mai se preferisci. Quello che dico è solo un diverso modo di comprendere la progettazione dei programmi.
Junyu Wu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.