修改其他属性的属性
attributes that modify other attributes
我想制作一个具有以下行为的 Block
class:如果设置了 iip3,则 oip3 设置为 iip3 + gain。如果设置了 oip3,则 iip3 设置为 oip3 - 增益如下:
b = Block(gain = 10)
Block(gain=10, iip3=inf, oip3=inf)
b.oip3 = 30
Block(gain=10, iip3=20, oip3=30)
b.iip3 = 21
Block(gain=10, iip3=21, oip3=31)
我已经用 attrs 模块试过了:
import attr
import numpy as np
def set_oip3(instance, attribute, iip3):
instance.oip3 = iip3 + instance.gain
return iip3
def set_iip3(instance, attribute, oip3):
instance.iip3 = oip3 - instance.gain
return oip3
@attr.s
class Block:
gain = attr.ib()
iip3 = attr.ib(on_setattr=set_oip3, default=np.inf)
oip3 = attr.ib(on_setattr=set_iip3, default=np.inf)
但是,这不起作用。我怀疑对 set_oip3
的调用会导致对 set iip3 的调用,而 iip3 又会调用 set oip3.
必须有一个使用 attrs 的解决方案。
您可以使用 @property
装饰器:
import numpy as np
class Block:
def __init__(self, gain=10, iip3=np.inf, oip3=np.inf):
self.gain = gain
self._iip3 = iip3
self._oip3 = oip3
def __repr__(self):
return f"Block(gain={self.gain}, iip3={self.iip3}, oip3={self.oip3})"
@property
def iip3(self):
return self._iip3
@iip3.setter
def iip3(self, val):
self._iip3 = val
self._oip3 = self._iip3 + self.gain
@property
def oip3(self):
return self._oip3
@oip3.setter
def oip3(self, val):
self._oip3 = val
self._iip3 = self._oip3 - self.gain
用法:
In [2]: b = Block()
In [3]: b.iip3 = 21
In [4]: b
Out[4]: Block(gain=10, iip3=21, oip3=31)
In [5]: b.oip3 = 30
In [6]: b
Out[6]: Block(gain=10, iip3=20, oip3=30)
就其价值而言,让增变器对给定增变器应该修改的属性以外的属性产生副作用并不是一个好主意。
正如其他人所说,在属性更改时改变属性并不是一个好主意。但是如果你坚持,你可以通过使用 object.__setattr__
来绕过 on_setattr
钩子——这也是 attrs
在内部做的事情:
import attr
import numpy as np
def set_oip3(instance, attribute, iip3):
object.__setattr__(instance, "oip3", iip3 + instance.gain)
return iip3
def set_iip3(instance, attribute, oip3):
object.__setattr__(instance, "iip3", oip3 - instance.gain)
return oip3
@attr.define
class Block:
gain = attr.ib()
iip3 = attr.ib(on_setattr=set_oip3, default=np.inf)
oip3 = attr.ib(on_setattr=set_iip3, default=np.inf)
按照您的要求工作:
In [9]: b = Block(gain = 10)
In [10]: b
Out[10]: Block(gain=10, iip3=inf, oip3=inf)
In [11]: b.oip3 = 30
In [12]: b
Out[12]: Block(gain=10, iip3=20, oip3=30)
In [13]: b.iip3 = 21
In [14]: b
Out[14]: Block(gain=10, iip3=21, oip3=31)
我想制作一个具有以下行为的 Block
class:如果设置了 iip3,则 oip3 设置为 iip3 + gain。如果设置了 oip3,则 iip3 设置为 oip3 - 增益如下:
b = Block(gain = 10)
Block(gain=10, iip3=inf, oip3=inf)
b.oip3 = 30
Block(gain=10, iip3=20, oip3=30)
b.iip3 = 21
Block(gain=10, iip3=21, oip3=31)
我已经用 attrs 模块试过了:
import attr
import numpy as np
def set_oip3(instance, attribute, iip3):
instance.oip3 = iip3 + instance.gain
return iip3
def set_iip3(instance, attribute, oip3):
instance.iip3 = oip3 - instance.gain
return oip3
@attr.s
class Block:
gain = attr.ib()
iip3 = attr.ib(on_setattr=set_oip3, default=np.inf)
oip3 = attr.ib(on_setattr=set_iip3, default=np.inf)
但是,这不起作用。我怀疑对 set_oip3
的调用会导致对 set iip3 的调用,而 iip3 又会调用 set oip3.
必须有一个使用 attrs 的解决方案。
您可以使用 @property
装饰器:
import numpy as np
class Block:
def __init__(self, gain=10, iip3=np.inf, oip3=np.inf):
self.gain = gain
self._iip3 = iip3
self._oip3 = oip3
def __repr__(self):
return f"Block(gain={self.gain}, iip3={self.iip3}, oip3={self.oip3})"
@property
def iip3(self):
return self._iip3
@iip3.setter
def iip3(self, val):
self._iip3 = val
self._oip3 = self._iip3 + self.gain
@property
def oip3(self):
return self._oip3
@oip3.setter
def oip3(self, val):
self._oip3 = val
self._iip3 = self._oip3 - self.gain
用法:
In [2]: b = Block()
In [3]: b.iip3 = 21
In [4]: b
Out[4]: Block(gain=10, iip3=21, oip3=31)
In [5]: b.oip3 = 30
In [6]: b
Out[6]: Block(gain=10, iip3=20, oip3=30)
就其价值而言,让增变器对给定增变器应该修改的属性以外的属性产生副作用并不是一个好主意。
正如其他人所说,在属性更改时改变属性并不是一个好主意。但是如果你坚持,你可以通过使用 object.__setattr__
来绕过 on_setattr
钩子——这也是 attrs
在内部做的事情:
import attr
import numpy as np
def set_oip3(instance, attribute, iip3):
object.__setattr__(instance, "oip3", iip3 + instance.gain)
return iip3
def set_iip3(instance, attribute, oip3):
object.__setattr__(instance, "iip3", oip3 - instance.gain)
return oip3
@attr.define
class Block:
gain = attr.ib()
iip3 = attr.ib(on_setattr=set_oip3, default=np.inf)
oip3 = attr.ib(on_setattr=set_iip3, default=np.inf)
按照您的要求工作:
In [9]: b = Block(gain = 10)
In [10]: b
Out[10]: Block(gain=10, iip3=inf, oip3=inf)
In [11]: b.oip3 = 30
In [12]: b
Out[12]: Block(gain=10, iip3=20, oip3=30)
In [13]: b.iip3 = 21
In [14]: b
Out[14]: Block(gain=10, iip3=21, oip3=31)