为何isinstance()对ariadne.SchemaBindable及其子类均返回True?
为何isinstance()对ariadne.SchemaBindable及其子类均返回True?
哎,这个疑惑我太懂了!我之前用Ariadne开发的时候也碰到过类似的情况,咱们来把这个“反常识”的现象拆解清楚~
核心原因:SchemaBindable是个被自定义了类型检查逻辑的特殊类型
Ariadne里的SchemaBindable不是普通的Python类,它通过自定义类型检查逻辑(比如重载了__instancecheck__魔法方法,或者利用了PEP 544的Protocol特性),改写了isinstance()的判断规则:
- 普通情况下,
isinstance(obj, Cls)是检查obj是不是Cls的实例,但SchemaBindable的逻辑被改成了:只要是实现了它定义的绑定协议的类(包括它自己),都会被isinstance()判定为True。 - 这就解释了为什么
isinstance(ObjectType, SchemaBindable)返回True——因为ObjectType是符合SchemaBindable协议的类,框架特意让isinstance()能识别这类绑定类型。
为什么SchemaBindable自己也满足isinstance?
至于isinstance(SchemaBindable, SchemaBindable)返回True,这也是框架设计的一部分:SchemaBindable本身作为协议的定义者,也被纳入了自己的类型检查范围,或者它的元类实现让它满足这个判断条件。
而issubclass()返回True是正常的
issubclass(ObjectType, SchemaBindable)返回True完全符合预期,因为ObjectType、InputType这些确实是SchemaBindable的子类,这个是标准的继承关系判断。
解决你的扫描工具问题
如果你的工具只想捕获你自己代码里定义的SchemaBindable子类,而排除Ariadne自带的那些,可以加个模块归属的判断:
import inspect from ariadne import SchemaBindable def is_custom_schema_bindable(cls): # 只判定项目内模块定义的子类为True return issubclass(cls, SchemaBindable) and not inspect.getmodule(cls).__name__.startswith("ariadne") # 测试示例 from ariadne.objects import ObjectType class MyCustomBindable(SchemaBindable): def bind_to_schema(self, schema): pass print(is_custom_schema_bindable(ObjectType)) # False(Ariadne自带类) print(is_custom_schema_bindable(MyCustomBindable)) # True(你的自定义类)
简单说,这不是Python的bug,是Ariadne框架为了方便GraphQL schema绑定的类型检查,特意做的设计~
备注:内容来源于stack exchange,提问作者odigity
相关产品推荐
相关产品推荐

