В чем разница между @staticmethod и @classmethod в Python?
Возможно, вы видели код Python, подобный этому псевдокоду, который демонстрирует подписи различных типов методов и предоставляет строку документации для объяснения каждого из них:
class Foo(object):
def a_normal_instance_method(self, arg_1, kwarg_2=None):
'''
Return a value that is a function of the instance with its
attributes, and other arguments such as arg_1 and kwarg2
'''
@staticmethod
def a_static_method(arg_0):
'''
Return a value that is a function of arg_0. It does not know the
instance or class it is called from.
'''
@classmethod
def a_class_method(cls, arg1):
'''
Return a value that is a function of the class and other arguments.
respects subclassing, it is called with the class it is called from.
'''
Нормальный метод экземпляра
Сначала я объясню a_normal_instance_method
. Это точно называется " метод экземпляра ". Когда используется метод экземпляра, он используется как частичная функция (в отличие от функции total, определенной для всех значений при просмотре в исходном коде), то есть при использовании первый из аргументов предопределен как экземпляр объект со всеми заданными атрибутами. Он имеет экземпляр объекта, связанный с ним, и он должен быть вызван из экземпляра объекта. Как правило, он будет обращаться к различным атрибутам экземпляра.
Например, это экземпляр строки:
', '
если мы используем метод экземпляра, join
в этой строке, чтобы присоединиться к другой итерации,
вполне очевидно, что это функция экземпляра, в дополнение к функции итеративного списка, ['a', 'b', 'c']
:
>>> ', '.join(['a', 'b', 'c'])
'a, b, c'
Связанные методы
Методы экземпляра можно связать с помощью поиска по точкам для последующего использования.
Например, это связывает метод str.join
с экземпляром ':'
:
>>> join_with_colons = ':'.join
И позже мы можем использовать это как функцию, с которой уже связан первый аргумент. Таким образом, он работает как частичная функция в экземпляре:
>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'
Статический метод
Статический метод не принимает экземпляр в качестве аргумента.
Это очень похоже на функцию уровня модуля.
Однако функция уровня модуля должна находиться в модуле и специально импортироваться в другие места, где она используется.
Однако, если он присоединен к объекту, он будет удобно следовать за объектом через импорт и наследование.
Пример статического метода - str.maketrans
, перенесенный из модуля string
в Python 3. Это делает таблицу перевода пригодной для потребления str.translate
. Это выглядит довольно глупо при использовании из экземпляра строки, как показано ниже, но импорт функции из модуля string
довольно неуклюж, и приятно иметь возможность вызывать ее из класса, как в str.maketrans
# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
В Python 2 вы должны импортировать эту функцию из все менее полезного строкового модуля:
>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'
Метод класса
Метод класса похож на метод экземпляра в том, что он принимает неявный первый аргумент, но вместо того, чтобы брать экземпляр, он принимает класс. Часто они используются в качестве альтернативных конструкторов для лучшего семантического использования и поддерживают наследование.
Наиболее каноническим примером встроенного метода класса является dict.fromkeys
. Он используется в качестве альтернативного конструктора dict (хорошо подходит для случаев, когда вы знаете, какие у вас ключи, и хотите получить для них значение по умолчанию.)
>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}
Когда мы создаем подкласс dict, мы можем использовать тот же конструктор, который создает экземпляр подкласса.
>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>
См. Исходный код pandas для других подобных примеров альтернативных конструкторов, а также посмотрите официальную документацию Python по classmethod
и staticmethod
.