Сообщить об ошибке.

Метод объекта/экземпляра класса в Python

Методы - это функции, вызываемые с использованием точечной нотации. Если обратится к методу (функции, определенной в пространстве имен класса) через экземпляр, то получим специальный объект: объект привязанного метода (также называемого методом экземпляра). При вызове он добавляет аргумент self в список аргументов.

Обычно метод вызывается сразу после его привязки:

class MyClass:
    """Простой пример класса"""
    i = 12345

    def f(self):
        return 'hello world'

x = MyClass()
x.f()
# 'hello world'

В примере с классом MyClass метод экземпляра класса x.f() возвращает строку "hello world". Нет необходимости вызывать метод сразу, x.f - это объект метода класса и его можно сохранить и вызвать позже. В примере ниже - бесконечный цикл, который будет продолжать печатать "hello world".

xf = x.f
while True:
    print(xf())

Что именно происходит при вызове метода? Заметили, что x.f() был вызван без аргумента? Хотя в определение функции f() был указан один аргумент self. Python всегда вызывает исключение, когда функция, требующая аргумента, вызывается без него, даже если аргумент фактически не используется…

Особенность методов заключается в том, что объект экземпляра передается в качестве первого аргумента self функции. В примере вызов x.f() в точности эквивалентен вызову MyClass.f(x). В общем случае вызов метода со списком из n аргументов эквивалентен вызову соответствующей функции со списком аргументов, который создается путем вставки объекта экземпляра метода перед первым аргументом.

При ссылке на атрибут экземпляра, не являющийся атрибутом данных, выполняется поиск экземпляра класса. Если имя обозначает допустимый атрибут класса, который является объектом функции, объект метода создается путем упаковки указателей объекта экземпляра и объекта функции, только что найденных вместе в абстрактном объекте: это объект метода. Когда объект метода вызывается со списком аргументов, новый список аргументов создается из экземпляра класса и списка аргументов этого класса, а объект функции вызывается с этим новым списком аргументов.

Первый аргумент метода называется self. Это не более чем соглашение: имя self не имеет абсолютно никакого особого значения для Python. Обратите внимание, что не следуя соглашению, ваш код может быть менее читаемым для других программистов Python и также может быть написана некая программа для просмотра классов, которая будет основываться на этом соглашении.

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

Например:

# Функция, определенная вне класса
def f1(self, x, y):
    return min(x, x+y)

class C:
    f = f1

    def g(self):
        return 'hello world'

    h = g

Обратите внимание, что эта практика обычно только запутывает читателя программы. Теперь f, g и h - это все атрибуты класса C, которые относятся к функциональным объектам, и, следовательно, все они являются методами экземпляров класса C. Метод h точно эквивалентны g.

Методы могут вызывать другие методы, используя атрибуты метода собственного аргумента:

class Bag:
    def __init__(self):
        self.data = []

    def add(self, x):
        self.data.append(x)

    def addtwice(self, x):
        self.add(x)
        self.add(x)

Методы могут ссылаться на глобальные имена так же, как обычные функции. Глобальной областью видимости, связанной с методом, является модуль, содержащий его определение. Класс никогда не используется в качестве глобальной области видимости. Хотя редко встречаются веские причины для использования глобальных данных в методе, существует много законных вариантов использования глобальной области видимости. Функции и модули, импортированные в глобальную область, могут использоваться методами, а также функциями и классами, определенными в нем. Обычно класс, содержащий метод, сам определяется в этой глобальной области видимости.

Поддержка получения произвольных атрибутов методами.

Связанные методы имеют два специальных атрибута, доступных только для чтения: m.__ self__ - это объект, с которым работает метод, и m.__func__ - это функция, реализующая метод. Вызов m(arg-1, arg-2, ..., arg-n) полностью эквивалентен вызову m.__func__(m.__self__, arg-1, arg-2, ..., arg-n).

Как и объекты функций, связанные объекты методов поддерживают получение произвольных атрибутов. Однако, поскольку атрибуты метода фактически хранятся в базовом объекте функции (meth.__func__), то установка атрибутов метода для связанных методов запрещена. Попытка установить атрибут в методе приводит к возникновению исключения AttributeError. Чтобы установить атрибут метода, необходимо явно установить его для базового объекта функции:

>>> class C:
...     def method(self):
...         pass
...
>>> c = C()
>>> c.method.whoami = 'my name is method'  # can't set on the method
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# AttributeError: 'method' object has no attribute 'whoami'
>>> c.method.__func__.whoami = 'my name is method'
>>> c.method.whoami
# 'my name is method'