当匹配条件不满足时,Python的__subclasshook__为何被调用两次?
当__subclasshook__返回NotImplemented时issubclass的行为解析
咱们直接说核心:调用issubclass(A, B)时,如果B的__subclasshook__返回NotImplemented,Python不会直接把这个值作为结果返回,而是会走一套后续逻辑,最终返回布尔值。
先看你代码的运行结果:调用issubclass(Foo, MyIterable)时,先是触发MyIterable.__subclasshook__(Foo)返回NotImplemented,接着又触发了ConcreteClass.__subclasshook__(Foo)也返回NotImplemented,最终输出False。这背后的执行流程是这样的:
- 初始判断:调用
issubclass(C, ABC类)时,先调用ABC类自身的__subclasshook__(C)。如果返回True或False,直接用这个结果。 - 递归子类判断:如果ABC类的
__subclasshook__返回NotImplemented,Python会遍历这个ABC类的所有子类,依次调用每个子类的__subclasshook__(C)。 - 结果汇总:只要有一个子类的
__subclasshook__返回True,整个issubclass就返回True;如果所有相关的__subclasshook__都返回NotImplemented或False,最终返回False。
对应到你的代码:
MyIterable是ABC类,Foo没有实现__iter__,所以MyIterable.__subclasshook__(Foo)返回NotImplemented。- Python接着找到
MyIterable的子类ConcreteClass,调用它的__subclasshook__(Foo)(因为ConcreteClass继承了父类的__subclasshook__逻辑),同样检查到Foo没有__iter__,返回NotImplemented。 - 所有判断都没给出“是子类”的信号,所以
issubclass(Foo, MyIterable)最终返回False。
为什么返回的是False而不是NotImplemented?
issubclass是必须返回布尔值的内置函数,NotImplemented在这里只是一个信号值——它告诉Python:“我这个类的__subclasshook__没法判断C是不是子类,你去问问我的子类们”。当所有可能的判断都无法给出肯定答案时,Python就默认返回False。
验证例子
如果给ConcreteClass重写__subclasshook__,让它对Foo返回True:
class ConcreteClass(MyIterable): def __init__(self): print("Concrete class called!") @classmethod def __subclasshook__(cls, C): if C is Foo: return True return NotImplemented
再运行issubclass(Foo, MyIterable),就会返回True——因为ConcreteClass.__subclasshook__(Foo)给出了肯定判断。
内容的提问来源于stack exchange,提问作者20MikeMike
相关产品推荐
相关产品推荐

