为什么Python Exception的repr会记录传入__init__的所有参数?
设计逻辑
Exception默认的__repr__保留所有构造入参,是专门为调试场景设计的:
- 异常触发时,完整的入参是定位问题的核心上下文,哪怕自定义异常的
__init__只用了参数的部分属性,默认保留全部原始入参可以避免调试时缺失关键信息,不需要开发人员额外手动记录入参 - 异常作为错误信息载体,默认行为不做「参数是否有用」的假设,统一全量保留是适配所有业务场景的最低成本方案,如果有定制需求可以自行重写
__repr__/__str__方法覆盖默认行为
运行原理伪代码
Exception的入参保存逻辑是在__new__方法里实现的,和子类是否重写__init__无关:
class BaseException: # Python中所有异常的实际基类 def __new__(cls, *args, **kwargs): # 实例化第一步就把所有位置参数存到内置args属性 inst = super().__new__(cls) inst.args = args # 注:kwargs默认不会被存到args里,和原生行为一致 return inst def __repr__(self): # 拼接repr时直接读取预存的args即可 args_str = ", ".join(repr(a) for a in self.args) return f"{self.__module__}.{self.__class__.__name__}({args_str})" # Exception继承自BaseException,继承了全部上述逻辑 class Exception(BaseException): pass
你给出的示例中,A(B())调用时,父类Exception的__new__会先执行,把B()实例存到args属性里,哪怕你重写的A.__init__只用到了b.message,也不会影响已经存好的args,所以__repr__会直接输出这个实例。而普通的自定义类没有这套预存入参+拼接入参的__repr__逻辑,所以只会输出默认的类名+内存地址格式。
内容的提问来源于stack exchange,提问作者marwan
相关产品推荐
相关产品推荐

