Python getter方法中的验证
通常,当我在类中使用属性并且同时使用getter和setter方法时,我在setter中执行所有验证检查 另一方面,如果我想限制最终用户更改属性的值,但仍然需要执行验证,我该怎么办?我只是把支票放进了getter,虽然我不确定它是否真的属于那里Python getter方法中的验证,python,properties,getter,setter,Python,Properties,Getter,Setter,通常,当我在类中使用属性并且同时使用getter和setter方法时,我在setter中执行所有验证检查 另一方面,如果我想限制最终用户更改属性的值,但仍然需要执行验证,我该怎么办?我只是把支票放进了getter,虽然我不确定它是否真的属于那里 class Foo: def __init__(self, value): self.__value = value @property def value(self): if not isins
class Foo:
def __init__(self, value):
self.__value = value
@property
def value(self):
if not isinstance(value, int):
raise ValueError(f'Expecting an integer, got {type(value)}.')
else:
return self.__value
这很好,但问题是a)在访问属性之前不会进行验证,b)每次访问属性时都会执行验证,这可能会很昂贵
所以我做了下面的版本。它解决了上述问题,但它看起来和感觉都不对。有没有更好的方法来做到这一点:
class Foo:
def __init__(self, val):
self.__val = val
@property
def __val(self):
return self.__tmp
@__val.setter
def __val(self, value):
if not isinstance(value, int):
raise ValueError()
else:
self.__tmp = value
@property
def value(self):
return self.__val
我想,我也可以在\uuuu init\uuuu
中进行验证,但这也很难看
编辑:
>>> a = Foo('bar')
Traceback (most recent call last):
File "C:\python\block_model_variable_imputer\venv_fixed\lib\site-packages\IPython\core\interactiveshell.py", line 3437, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-8-637c10c15d73>", line 1, in <module>
a = Foo('bar')
File "<ipython-input-7-f7d16143eb85>", line 3, in __init__
self.__val = val
File "<ipython-input-7-f7d16143eb85>", line 12, in __val
raise ValueError()
ValueError
>a=Foo('bar'))
回溯(最近一次呼叫最后一次):
文件“C:\python\block\u model\u variable\u imputer\venv\u fixed\lib\site packages\IPython\core\interactiveshell.py”,第3437行,运行代码
exec(代码对象、self.user\u全局、self.user\n)
文件“”,第1行,在
a=Foo('bar'))
文件“”,第3行,在_init中__
self.u val=val
文件“”,第12行,在
提升值错误()
数值误差
我个人认为
Foo类:
定义初始值(自身,值):
如果不是isinstance(值,int):
raise TypeError(f'需要一个整数,得到{type(value)}'))
其他:
自我价值=价值
@财产
def值(自身):
返回self.\u值
注意,我使用了TypeError
而不是ValueError
,因为这是这里更合适的异常类型;)
这解决了这两个问题
a) 在访问属性之前,不会进行任何验证;b)每次访问属性时都会执行验证,这可能会导致成本高昂
也不会像在第二个代码段中那样引入额外的helper变量。让setter和getter(用于\uu val
)专门用于内部使用对我来说是一种不好的做法
如果第二个代码段的目标是为了可读性而将检查逻辑移出\uuuu init\uuuu
,则可以执行以下操作
Foo类:
定义初始值(自身,值):
自我检查值=自我检查值输入(值)
定义检查值输入(值):
如果不是isinstance(值,int):
raise TypeError(f'需要一个整数,得到{type(value)}'))
其他:
返回值
@财产
def值(自身):
返回self.\u值
这还有一个好处,即如果在某个时候确实需要以其他速度检查输入,例如,如果您决定亲自为值重新添加setter,则可以重用\u check\u value\u input
Foo类:
定义初始值(自身,值):
如果不是isinstance(值,int):
raise TypeError(f'需要一个整数,得到{type(value)}'))
其他:
自我价值=价值
@财产
def值(自身):
返回self.\u值
注意,我使用了TypeError
而不是ValueError
,因为这是这里更合适的异常类型;)
这解决了这两个问题
a) 在访问属性之前,不会进行任何验证;b)每次访问属性时都会执行验证,这可能会导致成本高昂
也不会像在第二个代码段中那样引入额外的helper变量。让setter和getter(用于\uu val
)专门用于内部使用对我来说是一种不好的做法
如果第二个代码段的目标是为了可读性而将检查逻辑移出\uuuu init\uuuu
,则可以执行以下操作
Foo类:
定义初始值(自身,值):
自我检查值=自我检查值输入(值)
定义检查值输入(值):
如果不是isinstance(值,int):
raise TypeError(f'需要一个整数,得到{type(value)}'))
其他:
返回值
@财产
def值(自身):
返回self.\u值
这还有一个好处,即如果在某些时候确实需要以其他速度检查输入,例如,如果您决定为值重新添加setter,那么您可以重用\u check\u value\u input
,哦,是的,这更有意义。我知道我把事情搞得太复杂了。哦,是的,这更有意义。我知道我把事情搞得太复杂了。