英文:
How can I verify that the object is still correct with these conditions when I update the attribute?
问题
如何在每次属性更新后运行检查?
class Test:
def __init__(self, A, B, C):
self.A = A
self.B = B
self.C = C
self.check()
def check(self):
if self.A + self.B + self.C > 10:
raise ValueError
def __str__(self):
return f'{self.A}, {self.B}, {self.C}'
t = Test(2, 2, 2)
t.A = 8
print(t)
# 输出: 8, 2, 2
我尝试使用__setattr__
,但这样会在对象尚未分配所有属性时执行检查。
英文:
How do I make the check run after every attribute update?
class Test:
def __init__(self, A, B, C):
self.A = A
self.B = B
self.C = C
self.check()
def check(self):
if self.A + self.B + self.C > 10:
raise ValueError
def __str__(self):
return f'{self.A}, {self.B}, {self.C}'
>> t = Test(2, 2, 2)
>> t.A = 8
>> print(t)
>> 8, 2, 2
I tried to do it with setattr but then the check will execute when not all attributes are assigned to the object yet
答案1
得分: 1
Here is the translated content you requested:
作为一种替代方案,可以在初始化之后禁用__setattr__
的链接解决方案,您可以将属性包装为属性,并编写显式的设置器,在分配给实际属性之前检查条件。
class Test:
def __init__(self, A, B, C):
self._A = A
self._B = B
self._C = C
def _check(self, **newValues):
d = {"A": self._A, "B": self._B, "C": self._C}
d.update(newValues)
if sum(d.values()) > 10:
raise ValueError
@property
def A(self):
return self._A
@A.setter
def A(self, value):
self._check(A=value)
self._A = value
@property
def B(self):
return self._B
@B.setter
def B(self, value):
self._check(B=value)
self._B = value
@property
def C(self):
return self._C
@C.setter
def C(self, value):
self._check(C=value)
self._C = value
def __str__(self):
return f'{self.A}, {self.B}, {self.C}'
t = Test(2, 2, 2)
t.B = 8 # ValueError
此外,根据您在问题中编写的check
的方式,您需要在进行检查之前更改对象。这意味着如果出现错误,对象仍然会被修改为可能是不正确的值。通过我在此答案中实现的方式,您可以在不更改实际值的情况下进行检查,因此如果出现错误,对象将保持不变。
英文:
As an alternative to linked solution with disabling __setattr__
until after initialisation, you can wrap the attributes as property, writing them explicit setters that check the condition before assigning to actual attribute.
class Test:
def __init__(self, A, B, C):
self._A = A
self._B = B
self._C = C
def _check(self, **newValues):
d = {"A": self._A, "B": self._B, "C": self._C}
d.update(newValues)
if sum(d.values()) > 10:
raise ValueError
@property
def A(self):
return self._A
@A.setter
def A(self, value):
self._check(A=value)
self._A = value
@property
def B(self):
return self._B
@B.setter
def B(self, value):
self._check(B=value)
self._B = value
@property
def C(self):
return self._C
@C.setter
def C(self, value):
self._check(C=value)
self._C = value
def __str__(self):
return f'{self.A}, {self.B}, {self.C}'
t = Test(2,2,2)
t.B = 8 # ValueError
Also, with check
written the way you did in your question, you need to change the object before making the check. Which means if error is thrown, the object will still be modified to presumably incorrect value. With the way I implemented it in this answer, you can make check without changing the actual value, so in case of error the object remains unchanged.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论