PEP 544中类对象与协议示例的类型检查困惑求解
理解PEP 544中类对象与协议的匹配示例
核心误区:类对象 vs 类实例
你搞混了类对象(比如C本身)和类实例(比如C())的类型检查逻辑。这个示例里是把类C直接赋值给变量,不是创建它的实例,所以类型检查器会从类对象自身的成员角度去匹配协议,而非类实例的成员。
未绑定方法的签名变化
类中定义的def meth(self, x: int) -> int,当作为类对象的属性(也就是C.meth)时,它是一个未绑定方法——此时self不再是自动传入的实例,而是需要显式传入的第一个参数。所以C.meth的实际签名等价于:
def meth(obj: C, x: int) -> int: ...
逐个分析匹配逻辑
为什么a: ProtoA = C报错?
ProtoA协议要求类对象拥有一个meth方法,签名为def meth(self, x: int) -> int。这里的self指的是类对象本身,也就是说,这个方法期望第一个参数是类对象,第二个是int类型。
但C.meth的第一个参数是C的实例(不是类对象),和ProtoA的要求不匹配,因此类型检查报错。
为什么b: ProtoB = C合法?
ProtoB协议的meth签名是def meth(self, obj: Any, x: int) -> int。这里的self是类对象,第二个参数obj是Any类型——而C.meth的第一个参数是C的实例(属于Any的子集),第二个参数是int,返回值也是int,完全符合签名兼容规则(参数类型可以是协议要求的超类型)。
简单说,当你调用b.meth(some_obj, 5)时,本质是调用C.meth(some_obj,5),some_obj可以是任何类型(包括C的实例),完全满足ProtoB的要求。
内容的提问来源于stack exchange,提问作者danielcaballero88
相关产品推荐
相关产品推荐

