Reputation: 4035
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__
Upvotes: 0
Views: 341
Reputation: 789
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)
Upvotes: 3
Reputation: 111
__init__()
is called when used with Class
__call__()
is called when used with object of Class
Upvotes: 0
Reputation: 37267
I'd say it's neither here.
The part of code that's causing confusion is
OAuth2Bearer(self._api_key, self.access_token)
You need to know one thing: While OAuth2Bearer
is the name of a class, it's also an object of class type
(a built-in class). So when you write the above line, what's actually called is
type.__call__()
This can be easily verified if you try this code:
print(repr(OAuth2Bearer.__call__))
it will return something like this:
<method-wrapper '__call__' of type object at 0x12345678>
What type.__call__
does and returns is well covered in other questions: It calls OAuth2Bearer.__new__()
to create an object, and then initialize that object with obj.__init__()
, and returns that object.
You can think of the content of OAuth2Bearer(self._api_key, self.access_token)
like this (pseudo-code for illustration purposes)
OAuth2Bearer(self._api_key, self.access_token):
obj = OAuth2Bearer.__new__(OAuth2Bearer, self._api_key, self.access_token)
obj.__init__()
return obj
Upvotes: 0