這里發布了一個非常相似的問題,但沒有接受的答案,沒有代碼示例,而且我真的不喜歡那里提供的唯一一個答案所建議的使用外部庫的想法。
以下代碼允許定義只讀實體屬性:
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
@property
def x(self):
return self._x
@property
def y(self):
return self._y
但我也想驗證用戶輸入。我想驗證,如果x和y有正確的型別。
這樣做的最pythonic/優雅的方式是什么?如果我提供 setter,屬性就不再是只讀的。
在建構式中執行輸入驗證是唯一的方法嗎?
uj5u.com熱心網友回復:
這是一種使用工廠函式來創建屬性的優雅且 Pythonic 的方法:
class ReadOnlyError(Exception):
"""Attempt made to assign a new value to something that can't be changed."""
# Based on recipe in book "Python Cookbook 3rd Edition" - section 9.21 -
# titled "Avoiding Repetitive Property Methods".
def readonly_typed_property(name, expected_type):
storage_name = '_' name
@property
def prop(self):
return getattr(self, storage_name)
@prop.setter
def prop(self, value):
if hasattr(self, storage_name):
raise ReadOnlyError('{!r} is read-only!'.format(name))
if not isinstance(value, expected_type):
raise TypeError('{!r} must be a {!r}'.format(name, expected_type.__name__))
setattr(self, storage_name, value)
return prop
class Point:
x = readonly_typed_property('x', int)
y = readonly_typed_property('y', int)
def __init__(self, x, y):
self.x = x
self.y = y
if __name__ == '__main__':
try:
p1 = Point(1, 2)
except Exception as e:
print('ERROR: No exception should have been raised for case 1.')
print(e)
else:
print('As expected, NO exception raised for case 1.')
print()
try:
p2 = Point('1', 2)
except TypeError as e:
print(e)
print(f'As expected, {type(e).__name__} exception raised for case 2.')
else:
print('ERROR: expected TypeError exception not raised for case 2')
print()
try:
p1.x = 42
except Exception as e:
print(e)
print(f'As expected, {type(e).__name__} exception raised for case 3.')
else:
print('ERROR: expected ReadOnlyError exception not raised for case 3')
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/387445.html
上一篇:物體框架驗證外部物體未被修改
