Это сообщение от static methods. В итоге:
- метода экземпляр: требуется экземпляр в качестве первого аргумента
- методы класса: требуется класс в качестве первого аргумента
- статических методы: не требуют ни в качестве первого аргумента
Что касается ваших вопросов:
- Да. Хотя имя переменной
self
является условным, оно относится к экземпляру.
- Статические методы могут использоваться для группировки подобных методов утилиты в одном классе.
- Для методов внутри класса вам необходимо либо добавить
self
в качестве первого аргумента, либо украсить его методом @staticmethod
. «Не оформленные методы» без аргументов вызовут ошибку.
Может быть более понятно, как это работает при вызове с аргументами. Модифицированный пример:
class TestClass:
weight = 200 # class attr
def __init__(self, size):
self.size = size # instance attr
def instance_mthd(self, val):
print("Instance method, with 'self':", self.size*val)
@classmethod
def class_mthd(cls, val):
print("Class method, with `cls`:", cls.weight*val)
@staticmethod
def static_mthd(val):
print("Static method, with neither args:", val)
a = TestClass(1000)
a.instance_mthd(2)
# Instance method, with 'self': 2000
TestClass.class_mthd(2)
# Class method, with `cls`: 400
a.static_mthd(2)
# Static method, with neither args: 2
В целом, вы можете думать о каждом методе в терминах доступа:
- Если вам необходимо получить доступ к экземпляру или компонент экземпляра (например, атрибут экземпляра), используйте метод экземпляра, поскольку он передает
self
в качестве первого аргумента.
- Аналогичным образом, если вам нужен доступ к классу, используйте метод класса.
- Если доступ к ни экземпляру, ни классу не важен, вы можете использовать статический метод.
Обратите внимание в приведенном выше примере, то же аргумент передается для каждого типа метода, но доступ к атрибутам экземпляра и класса различаются по self
и cls
соответственно.
Обратите внимание, есть способ доступа к компонентам класса метода экземпляра с помощью self.__class__
, тем самым устраняя необходимость метода класса:
...
def instance_mthd2(self, val):
print("Instance method, with class access via `self`:", self.__class__.weight*val)
...
a.instance_mthd2(2)
# Instance method, with class access via `self`: 400
REF: Я рекомендую смотреть talkразвития Раймонда Hettinger в класс Питона Инструментарий, который четко разъясняет цель каждого типа метода примерами.
Обратите внимание, что это не будет работать вообще в 2.x, а 'a.static_class()' не будет работать. – jonrsharpe
Добавьте '' TestClass.static() '' и '' a.static_class() '' в свои тестовые примеры и наблюдайте, что происходит. Это может помочь проиллюстрировать, почему «@ staticmethod» является полезным. –
* «Разве это не то, о чем статические методы?» - преимущество того, что можно вызвать его в экземпляре, состоит в том, что 'cls.whatever()' и 'self.whatever()' будут работать правильно, позволяя сохранить имя класса из ваших методов класса и экземпляра и правильно обрабатывать наследование. – jonrsharpe