Python扩展内置list方法时list.append()调用报错原因
super()调用父类方法与直接类名调用的差异及报错原因 首先给出问题复现代码:
class EvenOnly(list): def append(self, integer): if not isinstance(integer, int): raise TypeError(f"'{integer}' is not an integer.") if integer % 2: raise ValueError(f"'{integer}' is not an even integer") super().append(integer)
将末尾的super().append(integer)替换为list.append(integer)后,执行会抛出如下错误:
TypeError: descriptor 'append' for 'list' objects doesn't apply to a 'int' object
两种调用方式的核心区别
super().append(integer):super()会返回一个绑定了当前类实例self的特殊代理对象,调用代理对象的方法时,会自动将self作为第一个隐式参数传入父类方法,实际执行的传参是list.append(self, integer),完全符合实例方法的传参规则。list.append(integer):这是直接通过类名访问类上定义的未绑定实例方法,不会自动绑定当前实例,调用时不会隐式传入self,此时你只传入了一个参数integer,缺失了实例方法必需的实例参数。
报错的根本原因
Python里类中定义的实例方法本身是实现了描述符协议的对象,通过类名直接访问实例方法时,拿到的是未绑定的原始方法,它要求第一个位置参数必须是该类(或其子类)的实例,之后才是方法接收的业务参数。list的append方法真实签名是append(self, value):
- 当你写
list.append(integer)时,Python会把你传入的唯一参数integer(int类型),当做方法要求的第一个参数self做类型校验 - 校验发现传入的
self是int类型,不是list类的实例,就会抛出描述符不匹配的类型错误。
如果一定要显式指定父类调用方法,正确写法是手动传入当前实例self:
list.append(self, integer)
注意这种写法在多继承场景下不会遵循Python的MRO(方法解析顺序)链路,可能跳过MRO中其他协作类的同名方法逻辑,除非明确需要跳过MRO,否则日常开发优先使用super()做父类方法调用。
内容的提问来源于stack exchange,提问作者Joseph Coleridge
相关产品推荐
相关产品推荐

