Почему Pycharm предлагает изменить метод на статический

154

В новой версии Pycharm (3.1.3 Community Edition) предлагается преобразовать методы, которые не работают с текущим состоянием объекта, в статические.

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

Какова практическая причина этого? Какая-то микро-производительность (или память) -оптимизация?

zerkms
источник
3
Вы нажали "больше ..."? Вы ссылаетесь selfгде-нибудь внутри метода? (Если вопрос действительно в том, «почему дизайнеры PyCharm разработали его таким образом ... вам придется их задавать, а не ТАК ...)
Wooble
7
@Wooble: return 1реализация метода в виде одной строки. «Больше» не содержит ничего полезного
zerkms

Ответы:

190

PyCharm «думает», что вы, возможно, хотели иметь статический метод, но вы забыли объявить его статическим (используя @staticmethodдекоратор).

PyCharm предлагает это, потому что метод не использует self в своем теле и, следовательно, фактически не изменяет экземпляр класса . Следовательно, метод может быть статическим, то есть вызываться без передачи экземпляра класса или даже без создания экземпляра класса.

jolvi
источник
4
Так много людей ответили с этим ответом аромата. Я хотел бы добавить, что если вы знаете, что это определенно не будет статическим методом, то включите «throw NotImplementedError», пока вы там, чтобы быть уверенным, что вы не используете его, не завершив его.
Ричард Грин
1
Могут быть случаи, когда предупреждение PyCharm не оправдано тем, что мы не хотим ни статического метода, ни изменения состояния. С другой стороны, если метод еще не реализован, кажется, всегда хорошая идея поднять a NotImplementedError.
Jolvi
3
У меня есть случай, когда моя реализация по умолчанию возвращает константу, но мои подклассы могут возвращать значение в зависимости от self. В этом случае предупреждение пренебрежимо, и я отмечаю его # noinspection PyMethodMayBeStatic. Жаль, что IntelliJ IDEA не предлагает добавить этот запрещающий комментарий в контекстные меню для этого предупреждения.
Alfe
Я предлагаю изменить строгость проверки 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 »не вызывается».

В поддержку испуга OP, предлагая вам добавлять статический метод всякий раз, когда вы можете, это идет вразрез с принципом, что проще сделать код менее ограничивающим позже, чем сделать его более - создание статического метода делает его менее ограничивающим, так как вы можете вызовите class.f () вместо instance.f ().

Угадает, почему существует это предупреждение:

  • Он рекламирует статический метод . Это заставляет разработчиков осознать то, что они, возможно, хорошо намеревались.
  • Как указывает @ JohnWorrall, он привлекает ваше внимание, когда self случайно покинуло функцию.
  • Это сигнал к переосмыслению объектной модели; возможно функция не принадлежит этому классу вообще.
Боб Стейн
источник
1
«создание статического метода делает его менее ограничительным» - это не так. Например: полиморфные методы
zerkms
Я думаю, что последний пункт стоит повторить: «Почему вы делаете это методом, когда это явно функция?» Храните материал, который действительно нуждается в экземпляре, отдельно от структурного материала, который имеет отношение к какому-либо аспекту. Вы можете легко разделить его на отдельный модуль.
сентября
Правила @dhill прекрасны до тех пор, пока вы не придумаете разумное исключение. Я описал один, список обратных вызовов.
Боб Стейн
7
Добавление # noinspection PyMethodMayBeStaticвыше метода или класса подавляет предупреждение и, на мой взгляд, лучше, чем вызов пустого метода.
Дэвид Пярссон
1
@Talha: selfвообще не удаляется в Python3.
Junuxx
12

Я думаю, что причиной этого предупреждения является конфиг в Pycharm. Вы можете снять флажок Метод может быть статическим в Редактор-> Инспекция

Mincom
источник
12
У меня был вопрос, почему такая проверка вообще существует. Я понимаю, что могу выключить это. Извините, не ответ.
zerkms
9

Я согласен с ответами, приведенными здесь (метод не используется selfи поэтому может быть украшен @staticmethod).

Я хотел бы добавить, что вы, возможно, захотите переместить метод в функцию верхнего уровня вместо статического метода внутри класса. Подробности см. В этом вопросе и принятом ответе: python - следует ли использовать статические методы или функции верхнего уровня

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

TLO
источник
Действительно полезный ответ - возможно, 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, и предупреждение уходит!

Junuxx
источник
0

Причина, по которой Pycharm делает это как предупреждение, потому что Python передаст self в качестве первого аргумента при вызове не статического метода (не добавляет @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 (или this) в качестве аргумента в методе класса. Вы можете просто вызвать себя, как вам нужно внутри метода. Но Python "должен" передать себя в качестве аргумента метода.

Понимая это, вам не нужен обходной путь, как ответ @BobStein.

Джуню Ву
источник
Это проходит selfи что?
zerkms
@zerkms «@staticmethod» не передает «себя»
Junyu Wu
Я только что процитировал вас: «Python передаст себя в качестве первого аргумента ... Pycharm это знает». Ну и что? Пихарм знает это, я знаю это. В чем причина пометки метода?
zerkms
@zerkms, потому что Пихарм считает, что вашим первым параметром метода может быть не «я». Обычно ppl не разрабатывает param метода и никогда не использует его. Пихарм думает, что вы создаете статический метод, и не осознавал, что первый параметр не является «я», поэтому он ставит предупреждение по умолчанию. Эта путаница вызвана дизайном языка программирования. Я предлагаю вам следовать программному дизайну (даже если это кажется не очень хорошим паттерном), добавить «staticmethod», чтобы избежать путаницы. Это нормально, если вы добавите «я», тогда никогда не используйте его, если хотите. То, что я говорю, - это просто другой взгляд на понимание программирования.
Junyu Wu