Чому pycharm пропонує змінити метод на статичний


154

Новий випуск pycharm (версія 3.1.3 спільноти) пропонує перетворити методи, які не працюють із поточним станом об'єкта, у статичні.

введіть тут опис зображення

Яка практична причина цього? Якась мікропродуктивність (-на пам'ять) -оптимізація?


3
Ви натискали "докладніше ..."? Ви посилаєтесь selfдесь усередині методу? (Якщо питання насправді "чому дизайнери PyCharm спроектували це так ... вам доведеться їх задати, не так ..."
Wooble

7
@Wooble: існує return 1як рядова реалізація методу. "Більше" не містить нічого корисного
zerkms

Відповіді:


189

PyCharm "думає", що ви, можливо, хотіли мати статичний метод, але ви забули оголосити його статичним (використовуючи @staticmethodдекоратор).

PyCharm пропонує це, тому що метод не використовується self у своєму тілі, а значить, фактично не змінює екземпляр класу . Отже, метод може бути статичним, тобто називатися без передачі екземпляра класу або навіть не створивши екземпляр класу.


4
Так багато людей відповіли на цю смакову відповідь. Я хотів би додати, хоча, якщо ви знаєте, що це точно не буде статичним методом, тоді додайте "кинути NotImplementedError", поки ви там впевнені, що не будете використовувати його без завершення.
Річард Грін

1
Можуть бути випадки, коли попередження PyCharm є невиправданим, оскільки ми не хочемо статичного методу, ані змінити стан. З іншого боку, якщо метод ще не реалізований, завжди добре виглядатиме підсумком NotImplementedError.
jolvi

3
У мене випадок, що моє виконання за замовчуванням повертає константу, але мої підкласи можуть повертати значення залежно від self. У цьому випадку попередження нехтувати, і я позначаю це # noinspection PyMethodMayBeStatic. Прикро, що IntelliJ IDEA не пропонує додавати цей відключаючий коментар у контекстні меню для цього попередження.
Альфе

Я пропоную змінити суворість цієї перевірки PyCharm з "Попередження" на "Без підсвічування, лише виправити" в налаштуваннях PyCharm. (Це дає багато помилкових позитивних результатів для мене.)
maciek

51

Погоджено з @jolvi, @ArundasR та іншими, попередження відбувається на функції члена, яка не використовується self.

Якщо ви впевнені, що PyCharm помиляється, що функція не повинна бути a @staticmethod, і якщо ви цінуєте нульові попередження, ви можете змусити це відійти двома різними способами:

Обхід №1

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

def is_not_used(self):
    pass

Обхід №2 [Спасибі @ DavidPärsson ]

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

Програма, яку я мав для цього (причина, по якій я не міг використовувати @staticmethod), полягала в створенні таблиці функцій обробника для відповіді на поле підтипу протоколу. Усі обробники повинні були бути однакової форми курсу (статичні або нестатичні). Але деяким не траплялося нічого робити з екземпляром. Якщо я зробив ці статичні, я отримав би "TypeError: 'staticmethod' об'єкт не можна викликати".

На підтримку згубності ОП, пропонуючи вам додавати статичний метод, коли тільки можна, суперечить принципу, що пізніше зробити код менш обмежувальним, ніж зробити його більше - створення методу статичного робить його тепер менш обмежуючим, оскільки ви можете виклик class.f () замість instance.f ().

Відгадайте, чому існує таке попередження:

  • Він рекламує статичний метод . Це дає зрозуміти розробникам про те, що вони, можливо, задумали.
  • Як вказує @ JohnWorrall, він привертає вашу увагу, коли самоврядування було ненавмисно залишене з функції.
  • Це підказка переосмислення об'єктної моделі; можливо, функція взагалі не належить до цього класу.

1
"створення статичного методу робить його зараз менш обмежуючим" --- це зовсім не так. Напр .: поліморфні методи
zerkms

Я думаю, що в останньому пункті повторюється: "чому ти робиш це методом, коли це явно функція?" Майте речі, яким справді потрібен екземпляр, окремо від структурних речей, які стосуються певного аспекту. Потім можна легко поділити його на окремий модуль.
забій

@dhill Правила - це прекрасні речі до дня, коли ви придумаєте розумний виняток. Я описав один, список зворотних дзвінків.
Боб Штейн

7
Додавання # noinspection PyMethodMayBeStaticвище методу чи класу придушує попередження, і на мій погляд, краще, ніж викликати порожній метод.
David Pärsson

1
@Talha: selfвзагалі не видаляється в Python3.
Junuxx

12

Я думаю, що причина цього попередження налаштована в Pycharm. Ви можете зняти прапорець Метод вибору може бути статичним у Редакторі-> Перевірка


12
Моє запитання було, чому така інспекція навіть існує. Я розумію, що можу вимкнути це. Вибачте, не відповідь.
zerkms

9

Я погоджуюся з наведеними тут відповідями (метод не використовується selfі тому може бути прикрашений @staticmethod).

Я хотів би додати, що, можливо, ви хочете перенести метод на функцію верхнього рівня замість статичного методу всередині класу. Детальніше див. Це питання та прийняту відповідь: python - чи слід використовувати статичні методи чи функції вищого рівня

Переміщення методу до функції верхнього рівня також виправить попередження PyCharm.


Дуже корисна відповідь - можливо, PyCharm повинен перейменувати попередження на «метод може бути статичним або функцією верхнього рівня». Під час рефакторингу методу pycharm створить функцію верхнього рівня, а не статичний метод, якщо selfце не параметр.
Сузана

@tlo +1 для згадки про декоратора. У мене є клас із методом, який не використовує, selfі тому міг би бути на вищому рівні, однак це не є логічним, дивлячись на те, що робить цей метод - як на вищому рівні він виглядав би більше глобальним методом, поки це насправді це невеликий помічний метод для екземплярів, створених із цього класу. Отже, щоб мій код був логічно організованим, декоратор - ідеальне рішення.
Казимир

7

Я можу уявити наступні переваги того, що метод класу визначено як статичний:

  • ви можете викликати метод просто за допомогою імені класу, не потрібно його інстанціювати.

решта переваг, ймовірно, незначні, якщо вони є взагалі:

  • може бігти трохи швидше
  • збережіть трохи пам’яті

Так. Але річ у тому, що я не використовую це як статичний метод. Інакше це вже було б статично. Тож PyCharm радить це робити без поважних причин (?). "Решта переваг, ймовірно, незначні, якщо вони є взагалі" --- так, точно. Але якщо це так - це дурні поради від PyCharm
zerkms

1
@zerkms - це так, як це іде в деяких чарівних випадках :-)
Jan Vlcinsky

2
Статичні методи - ворог для створення хорошого програмного забезпечення. Вони втрачають багато принципів, тому bitбіг швидше - це не сенс (тому що вони працюють в операційній пам'яті, так це швидко в обох випадках), і, як ви знаєте, комп'ютери тепер мають bunchпам'ять, тому це вже не проблема. Також зверніть увагу на вашу першу думку: Це процесуальна поведінка, а не об'єктно орієнтована.
AmirHossein

4

Оскільки ви не зверталися до нього selfв barтілі методу, PyCharm запитує, чи не хотіли ви статиbar статичними. В інших мовах програмування, як-от Java, є очевидні причини оголошення статичного методу. У Python єдиною реальною перевагою статичного методу (AFIK) є можливість викликати його без екземпляра класу. Однак, якщо це єдина ваша причина, вам, ймовірно, краще працювати з функцією вищого рівня - як тут зауважте .

Коротше кажучи, я не на сто відсотків впевнений, чому це там. Я здогадуюсь, що вони, ймовірно, видалять його у майбутньому випуску.


3

Це повідомлення про помилку просто допомогло мені купу, оскільки я не зрозумів, що випадково написав свою функцію за допомогою мого тестового прикладу програвача

my_player.attributes[item] 

замість правильного шляху

self.attributes[item]

1

Це може бути трохи безладно, але іноді вам просто не потрібно отримувати доступ self, але ви вважаєте за краще тримати метод у класі, а не робити його статичним. Або ви просто хочете уникати додавати купу непривабливих декораторів. Ось кілька можливих шляхів вирішення цієї ситуації.

Якщо ваш метод має лише побічні ефекти, і вам не байдуже, що він повертає:

def bar(self):
    doing_something_without_self()
    return self

Якщо вам потрібно повернути значення:

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

Тепер ваш метод використовується self, і попередження відходить!


0

Причина, чому Pycharm робить це попередженням, оскільки Python передасть себе як перший аргумент при виклику жодного статичного методу (не додавати @staticmethod). Піхарм це знає.

Приклад:

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)

Я з Java, в Java "self" називається "this", вам не потрібно писати self (або це) як аргумент у методі класу. Ви можете просто зателефонувати самостійно, як вам потрібно всередині методу. Але Python "повинен" передати себе як аргумент методу.

Розуміючи це, вам не потрібна відповідь як відповідь @BobStein.


Проходить selfтак що?
zerkms

@zerkms "@staticmethod" не проходить "я"
Junyu Wu

Я щойно процитував вас: "Python передасть себе як перший аргумент ... Pycharm це знає". І що? Піхарм це знає, я це знаю. Яка причина маркувати метод?
zerkms

@zerkms тому, що Pycharm вважає, що ваш перший метод парам може бути не "Я". Зазвичай ppl не розробляє парам методу і ніколи не використовує його. Pycharm вважає, що ви створюєте статичний метод, і не зрозумів, що перший парам - це не "я", тому за замовчуванням ставить попередження. Ця плутанина викликана дизайном мови програмування. Я пропоную вам дотримуватися дизайну програми (навіть це здається не гарною схемою), додайте "статичний метод", щоб уникнути плутанини. Це абсолютно добре, якщо ви додасте "самості", то ніколи не використовуйте його, якщо хочете. Те, що я говорю, - це просто інша думка, розуміючи дизайн програми.
Джуню Ву
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.