__call__ 或 __init__ 在这里打电话?不明白是哪个以及为什么

__call__ or __init__ called here? Don't undestand which and why

编辑:不幸的是,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?

我读到了 __init____call__,但我仍然不明白这段代码中发生了什么

我不明白:

1.) 会调用哪个方法,__init____call__

2.) 如果 __init__,那么 __init__ 不会 return 任何东西

3.)如果__call__,则__call__不能带两个参数调用

我认为应该调用 __init__,因为我们有 X(),而不是下面示例中的 x() this answer:

x = X() # __init__ (constructor)
x() # __call__

我会说这两者都不是

导致混淆的代码部分是

OAuth2Bearer(self._api_key, self.access_token)

你需要知道一件事:虽然 OAuth2Bearer 是 class 的名称,但它也是 class type 的对象(内置 class).所以当你写上面这行的时候,实际上调用的是

type.__call__()

如果您尝试以下代码,可以很容易地验证这一点:

print(repr(OAuth2Bearer.__call__))

它将return像这样:

<method-wrapper '__call__' of type object at 0x12345678>

type.__call__ 做什么和 returns 在其他问题中有很好的介绍:它调用 OAuth2Bearer.__new__() 创建一个对象,然后用 obj.__init__() 初始化该对象,和 returns 那个对象.

你可以这样想OAuth2Bearer(self._api_key, self.access_token)的内容(伪代码说明)

OAuth2Bearer(self._api_key, self.access_token):
    obj = OAuth2Bearer.__new__(OAuth2Bearer, self._api_key, self.access_token)
    obj.__init__()
    return obj

__init__() 在与 Class

一起使用时被调用

__call__() 在与 Class

的对象一起使用时被调用

我相信 this 就是您要找的。

在 Python 中调用对象的行为由其类型 __call__ 控制,因此:

OAuth2Bearer(args)

其实是这样的:

type(OAuth2Bearer).__call__(OAuth2Bearer, args)

OAuth2Bearer 的类型是什么,也称为 "metaclass"?如果不是 type,则默认为 type 的子类(这由 Python 严格执行)。来自上面的link:

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

所以调用的结果就是object.__new__传递给object.__init__后的结果。 object.__new__ 基本上只是为一个新对象分配 space 并且是这样做的唯一方法 AFAIK。要调用 OAuth2Bearer.__call__,您必须调用实例:

OAuth2Bearer(init_args)(call_args)