“在现代Python中声明自定义异常的正确方法?”
很好,除非您的异常确实是更具体的异常的一种:
class MyException(Exception):
pass
或者更好(也许是完美的),而不是pass
提供一个文档字符串:
class MyException(Exception):
"""Raise for my specific kind of exception"""
子类化异常子类
来自文档
Exception
所有内置的,非系统退出的异常都派生自此类。所有用户定义的异常也应从此类派生。
这意味着,如果您的异常是一种更具体的异常,请将该异常归为子类,而不是泛型Exception
(其结果将是您仍然Exception
按照文档建议的方式派生)。另外,您至少可以提供一个文档字符串(并且不被迫使用pass
关键字):
class MyAppValueError(ValueError):
'''Raise when my specific value is wrong'''
设置可使用custom创建自己的属性__init__
。避免将dict作为位置参数传递,以后您的代码用户将感谢您。如果您使用不推荐使用的message属性,则自行分配该属性将避免出现DeprecationWarning
:
class MyAppValueError(ValueError):
'''Raise when a specific subset of values in context of app is wrong'''
def __init__(self, message, foo, *args):
self.message = message # without this you may get DeprecationWarning
# Special attribute you desire with your Error,
# perhaps the value that caused the error?:
self.foo = foo
# allow users initialize misc. arguments as any other builtin Error
super(MyAppValueError, self).__init__(message, foo, *args)
确实不需要自己编写__str__
或__repr__
。内置的非常好,您的合作继承可确保您使用它。
批判最佳答案
也许我错过了这个问题,但是为什么不呢?
class MyException(Exception):
pass
同样,上面的问题是,要捕获它,您必须专门为其命名(如果在其他位置创建,则将其导入)或捕获Exception(但您可能不准备处理所有类型的Exception,并且您应该只捕获您准备处理的异常)。与以下内容类似的批评,但除此之外,这不是通过进行初始化的方式super
,DeprecationWarning
如果您访问message属性,则会得到一个:
编辑:要覆盖某些内容(或传递额外的args),请执行以下操作:
class ValidationError(Exception):
def __init__(self, message, errors):
# Call the base class constructor with the parameters it needs
super(ValidationError, self).__init__(message)
# Now for your custom code...
self.errors = errors
这样,您可以将错误消息的字典传递给第二个参数,并在以后使用e.errors到达它。
它也需要传入两个参数(self
。除外)。这是一个有趣的约束,将来的用户可能不会欣赏。
直截了当-它违反了Liskov的可替代性。
我将演示两个错误:
>>> ValidationError('foo', 'bar', 'baz').message
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
ValidationError('foo', 'bar', 'baz').message
TypeError: __init__() takes exactly 3 arguments (4 given)
>>> ValidationError('foo', 'bar').message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foo'
相比:
>>> MyAppValueError('foo', 'FOO', 'bar').message
'foo'