class omnimethod(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return functools.partial(self.func, instance)
class Geocoder(object):
def __init__(self, api_key=None, client_id=None, private_key=None):
# omitted
pass
@omnimethod
def geocode(
self,
address,
sensor='false',
bounds='',
region='',
language='',
components=''):
if self is not None: # <-- here
return GeocoderResult(self.get_data(params=params))
else:
return GeocoderResult(Geocoder.get_data(params=params))
Exactly in this case.
I didn't understand. What does this "if self is not None" code snippet mean? What is its place in the case? This self is parameter, in the function parameter. But alone.
omnimethod
looks to be a decorator intended for a function it's applied to to be invoked either as an instance or a class method.
Let's call the original function original
and the result of applying the decorator, which becomes the geocode
attribute of class Geocoder
, decorated
.
Consider two calls:
Geocoder.geocode("some address") # 1
geocoder = Geocoder()
geocoder.geocode("some address") # 2
According to the descriptor protocol:
The call (1) will resolve to:
decorated.__get__(None, Geocoder)("some address")
, which returns the original function partially applied to None
:functools.partial(original, None)("some address")
, which, according to implementation of partial
, is the same as:original(None, "some address")
The call (2) will resolve to:
decorated.__get__(geocoder, Geocoder)("some address")
(where geocoder
is an instance of Geocoder
)functools.partial(original, geocoder)("some address")
original(geocoder, "some address")
Thus, self
will be None
inside the original function if it is invoked as a class method, necessitating the check.