这是虫子吗?Python属性不能正确用于+=

2024-04-19 22:25:25 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我今天在代码中遇到了这个讨厌的bug。我最近一直在使用Python属性,并在属性更新时使用它将属性的旧值保存在另一个变量中。所以当调用setter函数时,我需要保存旧值,然后传输新值。在

结果是,当对属性使用+=时,调用__iadd__方法,在适当的地方更新属性,然后调用setter。但到那时,旧的价值观已经失去了。下面是一些说明这个问题的代码。在

class Container(object):
    def __init__(self, val):
        self.val = val

    def __add__(self, other):
        print('in __add__', other)
        return Container(self.val + other.val)

    def __iadd__(self, other):
        print('in __iadd__:', other)
        self.val += other.val
        return self

    def __str__(self):
        return str(self.val)


class Test:
    def __init__(self):
        self._val = Container(0)

    @property
    def val(self):
        return self._val

    @val.setter
    def val(self, values):
        print("changing from {} to {}".format(self._val, values))
        self._val = values

test = Test()
print('val=', test.val)
test.val = Container(2)
print('val=', test.val)
test.val = test.val + Container(1)
print('val=', test.val)
test.val += Container(1)
print('val=', test.val)
test.val.__iadd__(Container(1))
print('val=', test.val)

运行时会产生以下结果:

^{pr2}$

它说是从4改为4,但实际上是3改为4,这被错过了。所以我想知道这是一个bug,我遗漏了什么,或者我不应该使用+=如果我处理的是一个属性并且需要旧值。在


Tags: 代码testselfreturn属性containerdefval
1条回答
网友
1楼 · 发布于 2024-04-19 22:25:25

棘手。可以在getter中缓存旧值。这有点烦人,因为缓存操作是在getter的每次调用上执行的,而不是在setter调用上执行的。但不管怎样。。。在

class Container(object):
    def __init__(self, val):
        self.val = val

    def __add__(self, other):
        print('in __add__', self.val, other)
        return Container(self.val + other.val)

    def __iadd__(self, other):
        print('in __iadd__:', self.val, other)
        self.val += other.val
        return self

    def __str__(self):
        return str(self.val)

class Test:
    def __init__(self):
        self._val = Container(0)
        self._prev_val = self._val.val

    @property
    def val(self):
        self._prev_val = self._val.val
        return self._val

    @val.setter
    def val(self, values):
        print("changing from {} to {}".format(self._prev_val, values))
        self._val = values

test = Test()
print('val=', test.val)
test.val = Container(2)
print('val=', test.val)
test.val = test.val + Container(1)
print('val=', test.val)
test.val += Container(1)
print('val=', test.val)
test.val.__iadd__(Container(1))
print('val=', test.val)

输出

^{pr2}$

相关问题 更多 >