众所周知,Python 3.x中的所有类都继承自object Base Class.因此,当我创建这样的空类时:

class A:
  pass

我可以拨打callable(A)hasattr(A, '__call__'),他们会显示True.

>>> callable(A)
True
>>> hasattr(A, '__call__')
True

__call__方法显然应该在对象类中,但令人惊讶的是,它不是:

>>> object.__dict__
mappingproxy({'__new__': <built-in method __new__ of type object at 0x10a155940>, '__repr__': <slot wrapper '__repr__' of 'object' objects>, '__hash__': <slot wrapper '__hash__' of 'object' objects>, '__str__': <slot wrapper '__str__' of 'object' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'object' objects>, '__setattr__': <slot wrapper '__setattr__' of 'object' objects>, '__delattr__': <slot wrapper '__delattr__' of 'object' objects>, '__lt__': <slot wrapper '__lt__' of 'object' objects>, '__le__': <slot wrapper '__le__' of 'object' objects>, '__eq__': <slot wrapper '__eq__' of 'object' objects>, '__ne__': <slot wrapper '__ne__' of 'object' objects>, '__gt__': <slot wrapper '__gt__' of 'object' objects>, '__ge__': <slot wrapper '__ge__' of 'object' objects>, '__init__': <slot wrapper '__init__' of 'object' objects>, '__reduce_ex__': <method '__reduce_ex__' of 'object' objects>, '__reduce__': <method '__reduce__' of 'object' objects>, '__getstate__': <method '__getstate__' of 'object' objects>, '__subclasshook__': <method '__subclasshook__' of 'object' objects>, '__init_subclass__': <method '__init_subclass__' of 'object' objects>, '__format__': <method '__format__' of 'object' objects>, '__sizeof__': <method '__sizeof__' of 'object' objects>, '__dir__': <method '__dir__' of 'object' objects>, '__class__': <attribute '__class__' of 'object' objects>, '__doc__': 'The base class of the class hierarchy.\n\nWhen called, it accepts no arguments and returns a new featureless\ninstance that has no instance attributes and cannot be given any.\n'})
>>> dir(object)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

那么问题是:如果A类不实现__call__,为什么它可以调用?嗯,type班怎么样?

>>> type(A)
<class 'type'>
>>> type.__dict__
mappingproxy({'__new__': <built-in method __new__ of type object at 0x10a155110>, '__repr__': <slot wrapper '__repr__' of 'type' objects>, '__call__': <slot wrapper '__call__' of 'type' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'type' objects>, '__setattr__': <slot wrapper '__setattr__' of 'type' objects>, '__delattr__': <slot wrapper '__delattr__' of 'type' objects>, '__init__': <slot wrapper '__init__' of 'type' objects>, '__or__': <slot wrapper '__or__' of 'type' objects>, '__ror__': <slot wrapper '__ror__' of 'type' objects>, 'mro': <method 'mro' of 'type' objects>, '__subclasses__': <method '__subclasses__' of 'type' objects>, '__prepare__': <method '__prepare__' of 'type' objects>, '__instancecheck__': <method '__instancecheck__' of 'type' objects>, '__subclasscheck__': <method '__subclasscheck__' of 'type' objects>, '__dir__': <method '__dir__' of 'type' objects>, '__sizeof__': <method '__sizeof__' of 'type' objects>, '__basicsize__': <member '__basicsize__' of 'type' objects>, '__itemsize__': <member '__itemsize__' of 'type' objects>, '__flags__': <member '__flags__' of 'type' objects>, '__weakrefoffset__': <member '__weakrefoffset__' of 'type' objects>, '__base__': <member '__base__' of 'type' objects>, '__dictoffset__': <member '__dictoffset__' of 'type' objects>, '__name__': <attribute '__name__' of 'type' objects>, '__qualname__': <attribute '__qualname__' of 'type' objects>, '__bases__': <attribute '__bases__' of 'type' objects>, '__mro__': <attribute '__mro__' of 'type' objects>, '__module__': <attribute '__module__' of 'type' objects>, '__abstractmethods__': <attribute '__abstractmethods__' of 'type' objects>, '__dict__': <attribute '__dict__' of 'type' objects>, '__doc__': <attribute '__doc__' of 'type' objects>, '__text_signature__': <attribute '__text_signature__' of 'type' objects>, '__annotations__': <attribute '__annotations__' of 'type' objects>, '__type_params__': <attribute '__type_params__' of 'type' objects>})
>>> dir(type)
['__abstractmethods__', '__annotations__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__delattr__', '__dict__', '__dictoffset__', '__dir__', '__doc__', '__eq__', '__flags__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__instancecheck__', '__itemsize__', '__le__', '__lt__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__or__', '__prepare__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__setattr__', '__sizeof__', '__str__', '__subclasscheck__', '__subclasses__', '__subclasshook__', '__text_signature__', '__type_params__', '__weakrefoffset__', 'mro']

正是在这里,给出了__call__方法,是否意味着A类实际上继承自类型类?

>>> isinstance(A, type)
True
>>> issubclass(A, type)
False

搞什么?好吧,A可能是类型类型的类对象本身(对于解释器),但不是类型的子集,好吧,让我们判断objecttypeA的MRO:

>>> A.mro()
[<class '__main__.A'>, <class 'object'>]
>>> object.mro()
[<class 'object'>]
>>> type.mro(object)
[<class 'object'>]
>>> type.mro(A)
[<class '__main__.A'>, <class 'object'>]
>>> type.mro(type)
[<class 'type'>, <class 'object'>]

我在这里:既然类型类是对象的子集,而A类是类型类型,为什么MRO不在列表中显示类型类?如果object base class没有__call__方法并且type类既不是A的超类也不是对象,为什么A仍然是callable

推荐答案

A不会继承自type;它(像所有类一样)是type中的instance.

A.__call__将定义A中的instance的含义,即

a = A()
a()  # a.__call__() or A.__call__(a)

为了使A本身可调用,您需要type(A)来定义__call__,这正是type所做的.

a = A()  # a = A.__call__() or a = type.__call__(A)

Python相关问答推荐

如何从FDaGrid实例中删除某些函数?

Class_weight参数不影响RandomForestClassifier不平衡数据集中的结果

将numpy数组存储在原始二进制文件中

对Numpy函数进行载体化

为什么tkinter框架没有被隐藏?

我想一列Panadas的Rashrame,这是一个URL,我保存为CSV,可以直接点击

Python+线程\TrocessPoolExecutor

如何并行化/加速并行numba代码?

寻找Regex模式返回与我当前函数类似的结果

导入错误:无法导入名称';操作';

为什么我的sundaram筛这么低效

在Google Drive中获取特定文件夹内的FolderID和文件夹名称

查看pandas字符列是否在字符串列中

如何获得3D点的平移和旋转,给定的点已经旋转?

Django.core.exceptions.SynchronousOnlyOperation您不能从异步上下文中调用它-请使用线程或SYNC_TO_ASYNC

利用SCIPY沿第一轴对数组进行内插

用0填充没有覆盖范围的垃圾箱

如何获取给定列中包含特定值的行号?

如何将验证器应用于PYDANC2中的EACHY_ITEM?

如何在不不断遇到ChromeDriver版本错误的情况下使用Selify?