Search code examples
pythonself

What does "if self is not None" mean in a method?


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.


Solution

  • 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.