Python中isinstance函数的CPython底层实现原理探究
isinstance的底层逻辑及你的模拟实现 先明确:你写的_isinstance函数是对Python中isinstance功能的近似模拟,但和CPython的实际实现有一些差异,下面逐行拆解你的代码逻辑,再对比实际CPython的底层机制。
你的模拟函数逐行解释
def _isinstance(obj: object, cls: type) -> bool: # 检查obj是否实现了__instancecheck__魔术方法,且该方法可调用 if hasattr(obj, "__instancecheck__") and hasattr(obj.__instancecheck__, "__call__"): return obj.__instancecheck__(cls) # 判断obj是否是一个类(type的实例) if type(obj) is type: # 检查cls是否在obj的MRO(方法解析顺序)或obj的类(即type)中 return cls in (*obj.__mro__, obj.__class__) else: # obj是普通实例,检查cls是否在obj所属类的MRO中 return cls in obj.__class__.__mro__
1. 自定义实例检查逻辑分支
这部分是为了支持自定义类型或元类中实现的实例检查规则。比如某些框架或抽象基类(ABC)会通过__instancecheck__扩展isinstance的判断逻辑,你的代码优先调用obj自身的这个方法完成检查。
注:实际CPython中,是当第二个参数
cls实现了__instancecheck__时,才会调用cls.__instancecheck__(obj),你这里的逻辑刚好反过来,是检查obj的方法,这是和实际的差异点。
2. 处理obj是类的情况
当obj本身是一个类(比如int、自定义的Dog类),你的代码会把该类的MRO(比如Dog的MRO是[Dog, Animal, object])和该类的所属类(即type)合并,检查cls是否在这个集合里。
比如:
_isinstance(Dog, type)会返回True(因为type在集合中)_isinstance(Dog, Animal)也会返回True(因为Animal在Dog的MRO里)
注:这里和实际
isinstance行为不符——实际isinstance(Dog, Animal)会返回False,因为isinstance判断类是否是另一个类的实例,而非子类。正确逻辑应该是检查cls是否在type(obj).__mro__(即type的MRO:[type, object])中,而非obj自身的MRO。
3. 处理obj是普通实例的情况
这是最常见的场景:当obj是类的实例(比如dog = Dog()),代码会获取obj所属类的MRO,检查cls是否存在其中。比如_isinstance(dog, Animal)返回True,因为Animal在Dog的MRO里,符合isinstance的实际行为。
CPython中isinstance的底层实现逻辑
CPython的isinstance是C层面实现的,核心流程比你的模拟更严谨:
- 参数验证:首先检查第二个参数是否是类或类的元组(你的模拟只支持单个类,实际
isinstance支持isinstance(5, (int, str))这种元组形式) - 元组处理:如果第二个参数是元组,会递归遍历每个元素,只要有一个匹配就返回
True - 抽象基类检查:如果
cls是抽象基类(ABC),会调用cls.__instancecheck__(obj)来完成自定义检查 - MRO匹配:对于普通类,直接遍历
obj(如果是实例则取obj.__class__)的MRO,检查是否有类和cls完全匹配 - 缓存优化:CPython会缓存MRO的检查结果,避免重复计算提升性能
示例验证
用你的模拟函数测试几个场景:
class Animal: pass class Dog(Animal): pass dog = Dog() # 普通实例检查 print(_isinstance(dog, Dog)) # True(符合预期) print(_isinstance(dog, Animal)) # True(符合预期) print(_isinstance(dog, object)) # True(符合预期) # 类的检查 print(_isinstance(Dog, type)) # True(符合预期) print(_isinstance(Dog, Animal)) # True(实际isinstance返回False,这里是模拟逻辑的差异) print(_isinstance(type, object)) # True(符合预期)
内容的提问来源于stack exchange,提问作者Tigran

