Edit: this is unfortunately not answered in What is the difference between __init__ and __call__ in Python?
class OAuth2Bearer(requests.auth.AuthBase):
def __init__(self, api_key, access_token):
self._api_key = api_key
self._access_token = access_token
def __call__(self, r):
r.headers['Api-Key'] = self._api_key
r.headers['Authorization'] = "Bearer {}".format(self._access_token)
return r
#############
class AllegroAuthHandler(object):
def apply_auth(self):
return OAuth2Bearer(self._api_key, self.access_token) # what will happen here?
I read about __init__
and __call__
, but I still don't undestand what is going on in this code
I don't understand:
1.) Which method will be called, __init__
or __call__
2.) If __init__
, then __init__
doesn't return anything
3.) If __call__
, then __call__
can't be called with two parameters
I think __init__
should be called, because we have X()
, not x()
from example below as in this answer:
x = X() # __init__ (constructor)
x() # __call__
I believe this is what you're looking for.
The behaviour of calling an object in Python is governed by its type's __call__
, so this:
OAuth2Bearer(args)
Is actually this:
type(OAuth2Bearer).__call__(OAuth2Bearer, args)
What is the type of OAuth2Bearer
, also called its "metaclass"? If not type
, the default, then a subclass of type
(this is strictly enforced by Python). From the link above:
If we ignore error checking for a minute, then for regular class instantiation this is roughly equivalent to:
def __call__(obj_type, *args, **kwargs):
obj = obj_type.__new__(*args, **kwargs)
if obj is not None and issubclass(obj, obj_type):
obj.__init__(*args, **kwargs)
return obj
So the result of the call is the result of object.__new__
after passed to object.__init__
. object.__new__
basically just allocates space for a new object and is the only way of doing so AFAIK. To call OAuth2Bearer.__call__
, you would have to call the instance:
OAuth2Bearer(init_args)(call_args)