You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

当匹配条件不满足时,Python的__subclasshook__为何被调用两次?

当__subclasshook__返回NotImplemented时issubclass的行为解析

咱们直接说核心:调用issubclass(A, B)时,如果B的__subclasshook__返回NotImplemented,Python不会直接把这个值作为结果返回,而是会走一套后续逻辑,最终返回布尔值。

先看你代码的运行结果:调用issubclass(Foo, MyIterable)时,先是触发MyIterable.__subclasshook__(Foo)返回NotImplemented,接着又触发了ConcreteClass.__subclasshook__(Foo)也返回NotImplemented,最终输出False。这背后的执行流程是这样的:

  1. 初始判断:调用issubclass(C, ABC类)时,先调用ABC类自身的__subclasshook__(C)。如果返回True或False,直接用这个结果。
  2. 递归子类判断:如果ABC类的__subclasshook__返回NotImplemented,Python会遍历这个ABC类的所有子类,依次调用每个子类的__subclasshook__(C)。
  3. 结果汇总:只要有一个子类的__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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:30:45