自定义异常中的 __str__ 包装器

ale*_*lex 5 python exception decorator wrapper python-3.x

为什么下面的代码打印error msg而不是ABC\nerror msg

class CustomException(Exception):
    """ABC"""
    def __init__(self, *args):
        super().__init__(*args)
        self.__str__ = self._wrapper(self.__str__)
    def _wrapper(self, f):
        def _inner(*args, **kwargs):
            return self.__doc__ + '\n' + f(*args, **kwargs)
        return _inner

print(CustomException('error msg'))
Run Code Online (Sandbox Code Playgroud)

Mis*_*agi 1

由特殊方法支持的操作通常显式地将特殊方法查找为正确的方法,而不仅仅是可调用的属性。具体来说,解释器不是self.__str__粗略地查看type(self).__str__.__get__(self, type(self))\xe2\x80\x93 ,即要与实例绑定的类的描述符。__str__ 因此,要重写特殊方法,就需要重写类描述符而不是实例属性。

\n

这可以通过 a) 将特殊方法声明为处理该type(self).__str__部分的槽,以及 b) 分配一个处理该__get__(self, type(self))部分的函数来完成。

\n
class CustomException(Exception):\n    """ABC"""\n    __slots__ = ("__str__",)  # <<< magic\n\n    def __init__(self, *args):\n        super().__init__(*args)\n        # vvv self.__str__ is the class\' slot\n        self.__str__ = self._wrapper(super().__str__)\n        #                            AAA real __str__ lives on the super class\n    def _wrapper(self, f):\n        def _inner(*args, **kwargs):\n            return self.__doc__ + \'\\n\' + f(*args, **kwargs)\n        return _inner\n\nprint(CustomException(\'error msg\'))\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,由于在这种情况下每个实例的行为都相同,因此建议__str__在实践中仅定义一个新方法。

\n