Dlaczego pycharm proponuje zmianę metody na statyczną


154

Nowe wydanie pycharm (wydanie społeczności 3.1.3) proponuje konwersję metod, które nie działają z bieżącym stanem obiektu, na statyczne.

wprowadź opis obrazu tutaj

Jaki jest tego praktyczny powód? Jakiś rodzaj mikro-optymalizacji (-lub-pamięci) -optymalizacji?


3
Czy kliknąłeś „więcej ...”? Czy odnosisz się selfgdzieś w metodzie? (Jeśli pytanie naprawdę brzmi "dlaczego projektanci PyCharm zaprojektowali to w ten sposób ... będziesz musiał ich zapytać, a nie SO ...)
Wooble

7
@Wooble: istnieje return 1pojedyncza linia implementacji metody. „Więcej” nie zawiera niczego pożytecznego
zerkms

Odpowiedzi:


188

Pycharm „myśli”, że mogłeś chciał mieć metody statyczne, ale zapomniałeś o stwierdzenie, że jest statyczny (za pomocą @staticmethoddekoratora).

PyCharm proponuje to, ponieważ metoda nie używa self jej w treści i dlatego w rzeczywistości nie zmienia instancji klasy . W związku z tym metoda może być statyczna, tj. Wywoływalna bez przekazywania instancji klasy lub nawet bez jej utworzenia.


4
Tak wiele osób odpowiedziało tą odpowiedzią na smak. Dodałbym jednak, że jeśli wiesz, że na pewno nie będzie to metoda statyczna, dołącz "rzut NotImplementedError", gdy jesteś tam, aby mieć pewność, że nie użyjesz jej bez ukończenia.
Richard Green

1
Mogą wystąpić przypadki, w których ostrzeżenie PyCharm jest nieuzasadnione, ponieważ nie chcemy metody statycznej ani nie chcemy zmieniać stanu. Z drugiej strony, jeśli metoda nie została jeszcze zaimplementowana, zawsze dobrym pomysłem wydaje się podniesienie pliku NotImplementedError.
jolvi

3
Mam przypadek, w którym moja domyślna implementacja zwraca stałą, ale moje podklasy mogą zwracać wartość w zależności od self. W tym przypadku ostrzeżenie jest pomijalne i oznaczam je # noinspection PyMethodMayBeStatic. Szkoda, że ​​IntelliJ IDEA nie oferuje dodawania tego wyłączającego komentarza w menu kontekstowych tego ostrzeżenia.
Alfe

Proponuję zmienić stopień ważności tej inspekcji PyCharm z „Ostrzeżenie” na „Bez podświetlania, tylko napraw” w preferencjach PyCharm. (Daje mi to wiele fałszywych alarmów.)
maciek

51

Uzgodnione z @jolvi, @ArundasR i innymi, ostrzeżenie pojawia się w przypadku funkcji członkowskiej, która nie używa self.

Jeśli jesteś pewien, że PyCharm się myli, że funkcja nie powinna być a @staticmethod, a jeśli cenisz zero ostrzeżeń, możesz to zrobić na dwa różne sposoby:

Obejście nr 1

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

def is_not_used(self):
    pass

Obejście nr 2 [Thanks @ DavidPärsson ]

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

Aplikacja, którą miałem w tym celu (powód, dla którego nie mogłem użyć @staticmethod), polegała na tworzeniu tabeli funkcji obsługi odpowiadających na pole podtypu protokołu. Wszyscy przewodnicy musieli oczywiście mieć tę samą formę (statyczną lub niestatyczną). Ale niektórzy nie zrobili nic z instancją. Gdybym uczynił te statyczne, dostałbym "TypeError: 'staticmethod' object is not callable".

Na poparcie konsternacji PO, sugerowanie dodawania metody statycznej, kiedy tylko jest to możliwe, jest sprzeczne z tą zasadą , że łatwiej jest uczynić kod mniej restrykcyjnym później, niż uczynić go bardziej - uczynienie metody statyczną czyni ją mniej restrykcyjną teraz, ponieważ można wywołaj class.f () zamiast instance.f ().

Zgadnij, dlaczego istnieje to ostrzeżenie:

  • To reklamuje staticmethod . Uświadamia programistom coś, co mogli zamienić.
  • Jak wskazuje @ JohnWorrall's, przyciąga twoją uwagę, gdy jaźń została nieumyślnie pominięta w funkcji.
  • Jest to wskazówka do ponownego przemyślenia modelu obiektowego; może funkcja w ogóle nie należy do tej klasy.

1
„uczynienie metody statyczną czyni ją teraz mniej restrykcyjną” - wcale tak nie jest. Np .: metody polimorficzne
zerkmy

Myślę, że ostatnia kwestia wymaga powtórzenia: "dlaczego robisz z tego metodę, skoro jest to wyraźnie funkcja?" Trzymaj rzeczy, które naprawdę potrzebują instancji, oddzielone od rzeczy strukturalnych, które dotyczą jakiegoś aspektu. Możesz wtedy łatwo podzielić go na oddzielny moduł.
dhill

Zasady @dhill są piękne do dnia, w którym wymyślisz rozsądny wyjątek. Opisałem jedną, listę oddzwonień.
Bob Stein

7
Dodanie # noinspection PyMethodMayBeStaticpowyżej metody lub klasy pomija ostrzeżenie i jest moim zdaniem lepsze niż wywołanie metody pustej.
David Pärsson

1
@Talha: selfnie jest w ogóle usuwany w Python3.
Junuxx

12

Myślę, że powodem tego ostrzeżenia jest config w Pycharm. Możesz odznaczyć wybór Metoda może być statyczna w Edytorze-> Inspekcja


12
Moje pytanie brzmiało, dlaczego taka inspekcja w ogóle istnieje. Rozumiem, że mogę to wyłączyć. Przepraszam, brak odpowiedzi.
zerkms

9

Zgadzam się z odpowiedziami podanymi tutaj (metoda nie używa selfi dlatego można ją ozdobić @staticmethod).

Chciałbym dodać, że być może chcesz przenieść metodę do funkcji najwyższego poziomu zamiast metody statycznej wewnątrz klasy. Po szczegóły zobacz to pytanie i zaakceptowaną odpowiedź: python - czy powinienem używać metod statycznych czy funkcji najwyższego poziomu

Przeniesienie metody do funkcji najwyższego poziomu naprawi również ostrzeżenie PyCharm.


Naprawdę pomocna odpowiedź - może PyCharm powinien zmienić nazwę ostrzeżenia na „metoda może być funkcją statyczną lub najwyższego poziomu”. Podczas refaktoryzacji metody pycharm utworzy funkcję najwyższego poziomu, a nie metodę statyczną, jeśli selfnie jest to parametr.
Suzana

@tlo +1 za wzmiankę o dekoratorze. Mam klasę z metodą, która nie używa selfi dlatego mogłaby być na najwyższym poziomie, jednak nie wydaje się to logiczne, patrząc na to, co robi ta metoda - jako najwyższy poziom wyglądałby bardziej na metodę globalną, podczas gdy jest w rzeczywistości mała metoda pomocnicza dla instancji utworzonych z tej klasy. Aby mój kod był logicznie zorganizowany, dekorator jest idealnym rozwiązaniem.
kasimir

7

Mogę sobie wyobrazić następujące zalety posiadania metody klasowej zdefiniowanej jako statyczna:

  • możesz wywołać metodę używając nazwy klasy, bez potrzeby jej tworzenia.

pozostałe zalety są prawdopodobnie marginalne, jeśli w ogóle występują:

  • może działać trochę szybciej
  • zaoszczędzić trochę pamięci

Tak. Ale rzecz w tym, że nie używam tego jako metody statycznej. W przeciwnym razie byłby już statyczny. PyCharm radzi więc, aby zrobić to bez powodu (?). „pozostałe zalety są prawdopodobnie marginalne, jeśli w ogóle występują” - tak, dokładnie. Ale jeśli tak jest - to głupia rada od PyCharm
zerkms

1
@zerkms tak to wygląda z kilkoma uroczymi instancjami :-)
Jan Vlcinsky

2
Metody statyczne są wrogiem tworzenia dobrego oprogramowania. Uwalniają one wiele zasad, więc bitszybsze działanie nie jest celem (ponieważ działają w bunchpamięci RAM, więc jest szybki w obu przypadkach), a jak wiesz, komputery mają teraz pamięć, więc nie stanowi to już problemu. Zwróć też uwagę na swoją pierwszą myśl: jest to zachowanie proceduralne, a nie obiektowe.
AmirHossein

4

Ponieważ nie odwołałeś się selfw bartreści metody, PyCharm pyta, czy mógłbyś chcieć zrobić barstatyczne. W innych językach programowania, takich jak Java, istnieją oczywiste powody deklarowania metody statycznej. W Pythonie jedyną realną korzyścią dla metody statycznej (AFIK) jest możliwość wywołania jej bez instancji tej klasy. Jeśli jednak to twój jedyny powód, prawdopodobnie lepiej będzie, jeśli wybierzesz funkcję najwyższego poziomu - jak zauważ tutaj .

Krótko mówiąc, nie jestem w stu procentach pewien, dlaczego tam jest. Zgaduję, że prawdopodobnie usuną go w nadchodzącej wersji.


3

Ten komunikat o błędzie tylko mi pomógł, ponieważ nie zdawałem sobie sprawy, że przypadkowo napisałem swoją funkcję za pomocą mojego testowego odtwarzacza

my_player.attributes[item] 

zamiast we właściwy sposób

self.attributes[item]

1

Może to być trochę bałaganiarskie, ale czasami po prostu nie potrzebujesz dostępu self, ale wolisz zachować metodę w klasie i nie ustawiać jej statycznie. Lub po prostu chcesz uniknąć dodawania wielu nieestetycznych dekoratorów. Oto kilka potencjalnych obejść tej sytuacji.

Jeśli Twoja metoda ma tylko skutki uboczne i nie obchodzi Cię, co zwróci:

def bar(self):
    doing_something_without_self()
    return self

Jeśli potrzebujesz wartości zwracanej:

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

Teraz Twoja metoda używa self, a ostrzeżenie zniknie!


0

Powód, dla którego Pycharm robi to jako ostrzeżenie, ponieważ Python przekaże self jako pierwszy argument podczas wywoływania metody statycznej none (nie dodaje @staticmethod). Pycharm o tym wie.

Przykład:

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)

Jestem z Javy, w Javie "self" nazywa się "this", nie musisz pisać self (lub this) jako argumentu w metodzie klasowej. Możesz po prostu zadzwonić do siebie w ramach metody. Ale Python „musi” przekazać self jako argument metody.

Rozumiejąc to, nie potrzebujesz żadnego Obejścia, ponieważ odpowiedź @BobStein.


I selfco mija ?
zerkms

@zerkms '@staticmethod' nie przechodzi 'self'
Junyu Wu

Właśnie zacytowałem: „Python przejdzie przez siebie jako pierwszy argument ... Pycharm o tym wie.”. Więc co? Pycharm to wie, ja to wiem. Jaki jest powód zaznaczenia metody?
zerkms

@zerkms, ponieważ Pycharm uważa, że ​​pierwszym parametrem metody może nie być „self”. Zwykle ppl nie zaprojektuje parametru metody i nigdy go nie użyje. Pycharm uważa, że ​​tworzysz metodę statyczną i nie zdawał sobie sprawy, że pierwszy parametr nie jest „ja”, więc domyślnie wyświetla ostrzeżenie. To zamieszanie spowodowane projektem języka programowania. Proponuję postępować zgodnie z projektem programowania (nawet jeśli nie wydaje się to dobrym wzorcem), dodać „metodę statyczną”, aby uniknąć nieporozumień. Jest całkowicie w porządku, jeśli dodasz „siebie”, a następnie nigdy go nie używaj, jeśli wolisz. To, co mówię, jest po prostu inną opcją, jeśli chodzi o zrozumienie projektowania programowania.
Junyu Wu
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.