Метод Python, полученный с помощью getattr (), не нуждается в «self» в вызове? Почему нет?

#python #getattr

#python #getattr

Вопрос:

Работает следующий код:

 class Foo:
    def run_this(self):
        print("ran this")

ff = Foo()
method = getattr(ff, "run_this")
method()
--
run_this
 

Но я не понимаю, почему. Если getattr возвращает объект функции, мне нужно передать self объект в качестве первого аргумента. Кажется, что method это все-таки не объект функции, но я не уверен, что это такое. Почему self передается при вызове method() ?

В документах говорится только

getattr(объект, имя [, по умолчанию]) Возвращает значение именованного атрибута объекта. имя должно быть строкой. Если строка является именем одного из атрибутов объекта, результатом является значение этого атрибута. Например, getattr(x, `foobar`) эквивалентно x.foobar . Если именованный атрибут не существует, возвращается значение по умолчанию, если оно указано, в противном случае возникает ошибка AttributeError .

Таким образом, они отвечают на вопрос «что происходит», но не на вопрос о том, почему это работает таким образом.

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

1. getattr(obj, 'method')() не нуждается в self аргументе по той же причине obj.method() , что и нет — он уже привязан к объекту при поиске атрибута. Без объяснения того, почему, по вашему мнению getattr , строковый литерал должен вести себя иначе, чем обычный доступ к атрибутам, я не уверен, какой другой ответ вас удовлетворит.

2. getattr(obj, 'method') возвращает «связанный метод», который по сути является тем же самым, functools.partial что и метод с первым аргументом, связанным с obj

3. Потому что это эквивалентно method = ff.run_this , который по той же причине не требуется self в качестве аргумента. По той же причине ff.run_this() нет

4. Если вы хотите понять, как все это работает в принципе, вам нужно понимать, что функциональные объекты — это дескрипторы, __get__ метод которых частично применяет экземпляр при обращении к экземпляру. Прочитайте следующее: docs.python.org/3/howto/descriptor.html