Sử dụng __getattr__
và thuộc tính trong cùng một lớp là nguy hiểm, vì nó có thể dẫn đến lỗi rất khó gỡ lỗi.
Nếu bộ thu của tài sản ném AttributeError
, thì AttributeError
bị âm thầm bắt và __getattr__
được gọi. Thông thường, điều này gây ra __getattr__
để thất bại với một ngoại lệ, nhưng nếu bạn là vô cùng không may mắn, nó không, và bạn thậm chí sẽ không thể dễ dàng theo dõi vấn đề trở lại __getattr__
.
Trừ khi tài sản của bạn getter là tầm thường, bạn không bao giờ có thể chắc chắn 100% nó sẽ không ném AttributeError
. Ngoại lệ có thể bị ném nhiều cấp độ sâu.
Đây là những gì bạn có thể làm:
- Tránh sử dụng tài sản và
__getattr__
trong cùng một lớp.
- Thêm một khối
try ... except
cho tất cả các thu khí tài sản mà không phải là tầm thường
- Giữ getters tài sản đơn giản, vì vậy bạn biết rằng họ sẽ không ném
AttributeError
- Viết phiên bản của riêng bạn của
@property
trang trí, mà bắt AttributeError
và tái ném nó như RuntimeError
.
Xem thêm http://blog.devork.be/2011/06/using-getattr-and-property_17.html
EDIT: Trong trường hợp bất cứ ai đang cân nhắc giải pháp 4 (mà tôi không đề nghị), nó có thể được thực hiện như thế này:
def property_(f):
def getter(*args, **kwargs):
try:
return f(*args, **kwargs)
except AttributeError as e:
raise RuntimeError, "Wrapped AttributeError: " + str(e), sys.exc_info()[2]
return property(getter)
Sau đó sử dụng @property_
thay vì @property
trong các lớp ghi đè __getattr__
.
Nguồn
2014-06-17 10:03:51
Tôi sẽ nói rằng sự thất bại của tài liệu là nó nói rằng 'AttributeError' có thể được nâng lên trong' __get__' (đó là những gì bạn đang thực hiện ở đây) nhưng không giải thích hiệu ứng có. Nó có lẽ nên nói rằng 'AttributeError' tín hiệu để python rằng nó sẽ hành xử như thể thuộc tính đã không được tìm thấy (để' __getattr__' được cố gắng như một bản sao lưu, như thường lệ) - nếu đó không phải là hành vi mà bạn muốn, sau đó bạn nên nâng thứ gì đó khác. – James