Подтвердить что ты не робот

Может кто-нибудь объяснить, как исходный код staticmethod работает в python

Прежде всего, я понимаю, как работает декоратор. И я знаю, что @staticmethod удаляет аргумент экземпляра в подписи, делая

class C(object):
    @staticmethod
    def foo():
        print 'foo'
C.foo    //<function foo at 0x10efd4050>
C().foo  //<function foo at 0x10efd4050>

действует.

Однако я не понимаю, как это делает исходный код staticmethod.

Мне кажется, что при методе упаковки foo в staticmethod создается экземпляр staticmethod, затем происходит какая-то магия, делая C.foo() legit.

Итак... что происходит в этой магии? что сделал staticmethod?

Я знаю огромные темы о SO относительно staticmethods, но ни один из них не касается моих сомнений. Но, возможно, я не попал в волшебное ключевое слово. Если да, пожалуйста, сообщите мне.

Для тех, кто ищет исходный код staticmethod, обратитесь к https://hg.python.org/cpython/file/c6880edaf6f3/Objects/funcobject.c

4b9b3361

Ответ 1

Объект

A staticmethod - descriptor. Магия, которой вы не хватает, заключается в том, что Python вызывает метод __get__ при обращении к объекту как атрибут класса или экземпляра.

Таким образом, доступ к объекту как C.foo приводит к тому, что Python переводит это на C.__dict__['foo'].__get__(None, C), а instance_of_C.foo становится type(instace_of_C).__dict__['foo'].__get__(instance_of_C, type(instance_of_C)).

Объект staticmethod определенный в C-коде, но эквивалент в Python был бы следующим:

class staticmethod(object):
    def __init__(self, callable):
        self.f = callable
    def __get__(self, obj, type=None):
        return self.f
    @property
    def __func__(self):
        return self.f

где self.f - оригинальная обернутая функция.

Все это необходимо, потому что сами функции также являются дескрипторами; это протокол дескриптора, который предоставляет вам объекты метода (см. объект и объект связанного и закрытого метода python для получения более подробной информации). Поскольку у них тоже есть метод __get__, без объекта staticmethod, обертывающего функцию, вызов functionobj.__get__ вместо этого выдает объект метода, передавая его в аргументе self.

Существует также classmethod, который использует второй аргумент для descriptor.__get__ для привязки функции к классу, а затем есть объекты property, которые непосредственно переводит привязку в вызов функции. См. Как работает декоратор @property?.