"Cách thích hợp để khai báo các ngoại lệ tùy chỉnh trong Python hiện đại?"
Điều này là tốt, trừ khi ngoại lệ của bạn thực sự là một loại ngoại lệ cụ thể hơn:
class MyException(Exception):
pass
Hoặc tốt hơn (có thể là hoàn hảo), thay vì pass
đưa ra một chuỗi:
class MyException(Exception):
"""Raise for my specific kind of exception"""
Phân lớp ngoại lệ Phân lớp
Từ các tài liệu
Exception
Tất cả các ngoại lệ tích hợp, không thoát khỏi hệ thống đều có nguồn gốc từ lớp này. Tất cả các ngoại lệ do người dùng định nghĩa cũng nên được bắt nguồn từ lớp này.
Điều đó có nghĩa là nếu ngoại lệ của bạn là một loại ngoại lệ cụ thể hơn, thì lớp con ngoại lệ đó thay vì chung chung Exception
(và kết quả sẽ là bạn vẫn xuất phát từ Exception
các tài liệu khuyến nghị). Ngoài ra, ít nhất bạn có thể cung cấp một chuỗi doc (và không bị buộc phải sử dụng pass
từ khóa):
class MyAppValueError(ValueError):
'''Raise when my specific value is wrong'''
Đặt thuộc tính bạn tự tạo với một tùy chỉnh __init__
. Tránh chuyển một lệnh như một đối số vị trí, người dùng mã trong tương lai của bạn sẽ cảm ơn bạn. Nếu bạn sử dụng thuộc tính thông báo không dùng nữa, việc tự gán nó sẽ tránh 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)
Thực sự không cần phải viết của riêng bạn __str__
hay __repr__
. Các nội dung dựng sẵn rất đẹp và kế thừa hợp tác của bạn đảm bảo rằng bạn sử dụng nó.
Phê bình câu trả lời hàng đầu
Có thể tôi đã bỏ lỡ câu hỏi, nhưng tại sao không:
class MyException(Exception):
pass
Một lần nữa, vấn đề ở trên là để bắt được nó, bạn sẽ phải đặt tên cụ thể (nhập nó nếu được tạo ở nơi khác) hoặc bắt Ngoại lệ, (nhưng có lẽ bạn chưa sẵn sàng để xử lý tất cả các loại Ngoại lệ, và bạn chỉ nên bắt ngoại lệ bạn chuẩn bị xử lý). Những lời chỉ trích tương tự như bên dưới, nhưng ngoài ra, đó không phải là cách để khởi tạo thông qua super
và bạn sẽ nhận được DeprecationWarning
nếu bạn truy cập thuộc tính thư:
Chỉnh sửa: để ghi đè một cái gì đó (hoặc vượt qua các đối số phụ), hãy làm điều này:
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
Bằng cách đó, bạn có thể chuyển thông báo lỗi cho thông số lỗi thứ hai và truy cập nó sau với e.errors
Nó cũng đòi hỏi chính xác hai đối số được truyền vào (ngoài self
.) Không hơn, không kém. Đó là một hạn chế thú vị mà người dùng trong tương lai có thể không đánh giá cao.
Để được trực tiếp - nó vi phạm khả năng thay thế Liskov .
Tôi sẽ chứng minh cả hai lỗi:
>>> 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'
So với:
>>> MyAppValueError('foo', 'FOO', 'bar').message
'foo'