自动继承collections.Callable(及其他类)是如何工作的?
这个问题主要是关于Python 2的,不过我也想知道在Python 3中是否有区别。
我发现,当在类中创建某些方法时(不管这些类是新式类还是旧式类),Python会自动认为这些类是来自collections模块的一些类。下面的例子展示了这一点,特别是关于collections.Callable。
>>> import collections
>>> class A:
def __call__(self):
print "A"
>>> a = A()
>>> isinstance(a, collections.Callable)
True
>>> class A(object):
def __call__(self):
print "A"
>>> a = A()
>>> isinstance(a, collections.Callable)
True
>>> class A(object):
pass
>>> a = A()
>>> isinstance(a, collections.Callable)
False
>>> class A:
pass
>>> a = A()
>>> isinstance(a, collections.Callable)
False
你会注意到,我并没有明确让这些类继承collections.Callable,但只要它们创建了一个__call__
方法,Python就会自动把它们当作是这个类的实例。这是出于某种特定的目的吗?这个规则在某个地方有明确的说明吗?Python是不是在自动给类分配某些基类,仅仅因为定义了方法,还是说还有其他原因呢?
对于collections.Iterable和__iter__
方法,以及其他一些特殊方法,你也会得到类似的结果。
1 个回答
0
ABCMeta
类是用来定制实例和子类检查的工具,它提供了两个方法:__instancecheck__()
和 __subclasscheck__()
。
这些工具会调用 ABCMeta.__subclasshook__()
方法来进行具体的检查:
__subclasshook__(subclass)
这个方法用来检查 subclass 是否被认为是这个抽象基类(ABC)的子类。也就是说,你可以进一步定制
issubclass
的行为,而不需要在每个你想要认为是 ABC 子类的类上都调用register()
。
这个工具可以检查给定的子类是否实现了预期的方法;对于 Callable
类来说,检查的方式很简单,只需要看看是否有 __call__
方法:
@classmethod
def __subclasshook__(cls, C):
if cls is Callable:
if _hasattr(C, "__call__"):
return True
return NotImplemented
这个检查是专门针对 Callable
类的;如果你创建了子类,就需要自己实现相应的版本,因为你很可能会添加新的方法。