omnimethod
выглядит как декоратор, предназначенный для функции, к которой он применяется, для вызова в качестве экземпляра или метода класса.
Давайте назовем исходную функцию original
и результат применения декоратор, который становится атрибутом geocode
класса Geocoder
, decorated
.
. Рассмотрим два вызова:
Geocoder.geocode("some address") # 1
geocoder = Geocoder()
geocoder.geocode("some address") # 2
В соответствии с протоколом дескриптора :
Вызов (1) преобразуется в:
decorated.__get__(None, Geocoder)("some address")
, что возвращает исходную функцию, частично примененную к None
: functools.partial(original, None)("some address")
, который, согласно реализации partial
, совпадает с: original(None, "some address")
Вызов (2) будет разрешен в:
decorated.__get__(geocoder, Geocoder)("some address")
(где geocoder
является экземпляром Geocoder
) functools.partial(original, geocoder)("some address")
original(geocoder, "some address")
Таким образом, self
будет быть None
внутри исходной функции, если она вызывается как метод класса, что требует проверки.