Разница между наличием @staticmethod и его отсутствием

#python #python-3.x #python-decorators

#python #python-3.x #python-декораторы

Вопрос:

Что я могу сделать с Python 3.x, bar() с чем я не могу foo() ?

 class A:
    def foo():
        print("some code")

    @staticmethod
    def bar():
        print("some code")
  

Примечание: Изначально я забыл указать self в качестве аргумента foo() , но я оставляю ошибку там, поскольку ответы подчеркивают это.

Комментарии:

1. Определение foo должно быть def foo(self): , если вы планируете его вызывать 🙂

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

3. Пожалуйста, не меняйте вопрос, я уже обратился к вашей первоначальной версии — и ее стоит оставить в ответе..

4. Разница становится очевидной, как только self добавляется в качестве аргумента. Функция никогда бы не запустилась без self в любом случае

5. Итак, должен ли я вернуть его к исходному виду с ошибкой и оставить заметку для редактирования, чтобы какой-нибудь другой ученик мог ее подхватить?

Ответ №1:

staticmethod — это метод, который не требует объекта в качестве своего первого параметра. Это означает, что это метод, полезный для самого класса и всех его экземпляров, а не просто для его экземпляров (объект инициализирован как A() .

На практике это означает, что Python неявно отправляет сам объект в качестве параметра. Ваш первый метод сломается, как только вы его вызовете:

 >>> a.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes 0 positional arguments but 1 was given
  

Это потому, что Python предоставляет объектные методы с самим объектом в качестве первого параметра. Отсюда повсеместный аргумент self:

 def foo(self): #Proper signature
  

С другой стороны,

 A.bar()
  

будет работать просто отлично, и так будет

 a.bar()
  

Объект не предоставляется в качестве первого аргумента. Используйте staticmethod s для методов, которые должны быть полезны для класса и его экземпляров, но не требуют знания ни того, ни другого. Обычно я использую их как служебные функции.

Обратите внимание, что существует третья версия, a classmethod , которая похожа на обычный метод в том, что она принимает первый параметр по умолчанию — класс вызывающего. В этом случае минимальная сигнатура равна

 @classmethod
def operateOnClass(cls):
  

Используйте это для внесения изменений, которые влияют на все экземпляры, например, для изменения переменных класса.

Комментарии:

1. Возможно, важно упомянуть, что в python есть три типа методов: методы экземпляра, методы класса и статические методы.

2. Да, пожалуйста, уточните это, чтобы я мог получить более полную картину

3. @Будет выполнено. Каждый из них полезен для чего-то немного другого.

Ответ №2:

bar() может вызываться из не созданного объекта класса. foo() должен быть передан self в качестве аргумента и, как таковой, может быть вызван только из объекта, уже объявленного как экземпляр class A