Что такое «методы класса» и «методы экземпляра» в Python?
«Метод экземпляра» использует информацию, содержащуюся в экземпляре, чтобы выяснить, какое значение вернуть (или какой побочный эффект нужно сделать). Это очень распространено.
«Метод класса» использует информацию о классе (а не об экземпляре этого класса), чтобы повлиять на то, что он делает (они обычно используются для создания новых экземпляров в качестве альтернативных конструкторов и, следовательно, не являются невероятно распространенными).
«Статический метод» не использует никакой информации о классе или экземпляре для вычисления того, что он делает. Обычно это просто в классе для удобства. (Как таковые, они тоже не очень распространены.)
Функция Х
Помните математический класс, "у есть функция х f(x)
,?" Давайте применим это в коде:
y = function(x)
Под вышесказанным подразумевается, что поскольку x
могут меняться, y
могут меняться при x
изменениях. Это то, что подразумевается, когда мы говорим, что " y
является функцией x
"
Что будет y
когда z
есть 1
? 2
? 'FooBarBaz'
?
y
не является функцией z
, поэтому z
может быть чем угодно и не влиять на результат функции, предполагая, что наша функция function
является чистой. (Если он обращается z
как к глобальной переменной, то это не чистая функция - это то, что подразумевается под функциональной чистотой.)
Помните вышеупомянутое, читая следующие описания:
Методы экземпляра
Метод экземпляра является функцией , которая является функцией от экземпляра . Функция неявно принимает экземпляр в качестве аргумента, и экземпляр используется функцией для определения выходных данных функции.
Встроенным примером метода экземпляра является str.lower:
>>> 'ABC'.lower()
'abc'
str.lower
вызывается для экземпляра строки и использует информацию, содержащуюся в экземпляре, чтобы выяснить, какую новую строку возвращать.
Методы класса:
Помните, в Python все является объектом. Это означает, что класс является объектом и может быть передан в качестве аргумента функции.
Метод класса является функцией , которая является функцией от класса . Он принимает класс в качестве аргумента.
Встроенный пример dict.fromkeys
:
>>> dict.fromkeys('ABC')
{'C': None, 'B': None, 'A': None}
Функция неявно знает свой собственный класс, функция использует этот класс для воздействия на выходные данные функции и создает новый из этого класса из итерируемого. OrderedDict демонстрирует это при использовании того же метода:
>>> from collections import OrderedDict
>>> OrderedDict.fromkeys('ABC')
OrderedDict([('A', None), ('B', None), ('C', None)])
Метод класса использует информацию о классе (а не об экземпляре этого класса), чтобы повлиять на тип возвращаемого класса.
Статические Методы
Вы упоминаете метод, который «не знает своего класса» - это статический метод в Python. Это просто присоединено для удобства к объекту класса. При желании это может быть отдельная функция в другом модуле, но ее сигнатура вызова будет такой же.
Статический метод не является функцией ни класса, ни объекта.
Встроенным примером статического метода является str.maketrans из Python 3.
>>> str.maketrans('abc', 'bca')
{97: 98, 98: 99, 99: 97}
Учитывая пару аргументов, он создает словарь, который не является функцией своего класса.
Это удобно, потому что str
всегда доступно в глобальном пространстве имен, поэтому вы можете легко использовать его с функцией перевода:
>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
'bcrbabdbcrb'
В Python 2 вы должны получить к нему доступ из string
модуля:
>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'str' has no attribute 'maketrans'
>>> import string
>>> 'abracadabra'.translate(string.maketrans('abc', 'bca'))
'bcrbabdbcrb'
пример
class AClass(object):
"""In Python, a class may have several types of methods:
instance methods, class methods, and static methods
"""
def an_instance_method(self, x, y, z=None):
"""this is a function of the instance of the object
self is the object's instance
"""
return self.a_class_method(x, y)
@classmethod
def a_class_method(cls, x, y, z=None):
"""this is a function of the class of the object
cls is the object's class
"""
return cls.a_static_method(x, y, z=z)
@staticmethod
def a_static_method(x, y, z=None):
"""this is neither a function of the instance or class to
which it is attached
"""
return x, y, z
Давайте создадим:
>>> instance = AClass()
Теперь экземпляр может вызывать все методы:
>>> instance.an_instance_method('x', 'y')
('x', 'y', None)
>>> instance.a_static_method('x', 'y')
('x', 'y', None)
>>> instance.a_class_method('x', 'y')
('x', 'y', None)
Но обычно класс не предназначен для вызова метода экземпляра, хотя ожидается, что он вызовет другие:
>>> AClass.a_class_method('x', 'y')
('x', 'y', None)
>>> AClass.a_static_method('x', 'y')
('x', 'y', None)
>>> AClass.an_instance_method('x', 'y')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an_instance_method() missing 1 required positional argument: 'y'
Вы должны были бы явно передать экземпляр для вызова метода экземпляра:
>>> AClass.an_instance_method(instance, 'x', 'y')
('x', 'y', None)