我正在使用sqlalchemy定义映射的类。它包含三个用户定义的值(a,b,c)和一个从属值(abc),使用a,b和c计算得出。我想将侦听器附加到a,b和c,它们的值更改时会更新abc。使用会event.listen(variable.a, 'set', updateFunction)
调用该函数,该函数应更新abc。不幸的是,在将新值存储在变量中之前触发了该事件。因此,将使用旧值计算abc。
例:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, Numeric, Sequence
from sqlalchemy import event
base = declarative_base()
class demo(base):
__tablename__ = 'demo'
id = Column(Integer, Sequence('some_id_seq'), primary_key=True)
a = Column(Integer)
b = Column(Integer)
c = Column(Integer)
abc = Column(Numeric) #calculated from a, b, and c
def __init__(self, A, B, C):
self.a = A
self.b = B
self.c = C
self.calcABC() #initial calculation of abc
event.listen(demo.a, 'set', self.calcABCEvent, named=True)
event.listen(demo.b, 'set', self.calcABCEvent, named=True)
event.listen(demo.c, 'set', self.calcABCEvent, named=True)
#super complicated formular
def calcABC(self):
self.abc = ( self.a + self.b ) * self.c
#This event ist called, before the new value is set
#Thus the calculation is not correct
def calcABCEvent(self, target, value, oldvalue, initiator):
print("\nevent called")
print(f"self.a \t\t{self.a}")
print(f"target.a \t{target.a}")
print(f"oldvalue \t{oldvalue}")
print(f"value \t\t{value}") #The new value only appears in value
self.calcABC()
def __str__(self):
return f"({self.a} + {self.b}) * {self.c} = {self.abc}"
print("init")
obj = demo(1,2,3)
print(obj) #abc should be (1+2)*3 = 9
print("\nchange a to 4")
obj.a = 4
print("\nchanged object")
print(obj) #abc should be (4+2)*3 = 18
输出:
init
(1 + 2) * 3 = 9
change a to 4
event called
self.a 1
target.a 1
oldvalue 1
value 4
changed object
(4 + 2) * 3 = 9
如何仅使用一个功能更新abc?在我的应用程序中,abc是使用七个变量来计算的,我想避免编写七个更新函数。有类似的东西event.listen(variable.a, 'after_set', updateFunction)
吗?
在学习了属性之后发现了类似的疑问:通过SqlAlchemy中的@property实现Python getter和setter
我的解决方案如下所示:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, Numeric, Sequence
from sqlalchemy.ext.hybrid import hybrid_property
base = declarative_base()
class demo(base):
__tablename__ = 'demo'
id = Column(Integer, Sequence('some_id_seq'), primary_key=True)
_a = Column("a", Integer)
_b = Column("b", Integer)
_c = Column("c", Integer)
abc = Column(Numeric) #calculated from a, b, and c
def __init__(self, A, B, C):
self._a = A
self._b = B
self._c = C
self.calcABC() #inital calculation of abc
#super complicated formular
def calcABC(self):
self.abc = ( self._a + self._b ) * self._c
def __str__(self):
return f"({self._a} + {self._b}) * {self._c} = {self.abc}"
@hybrid_property
def a(self):
return self._a
@a.setter
def a(self, a):
self._a = a
self.calcABC()
@hybrid_property
def b(self):
return self._b
@b.setter
def b(self, b):
self._b = b
self.calcABC()
@hybrid_property
def c(self):
return self._c
@c.setter
def c(self, c):
self._c = c
self.calcABC()
print("init")
obj = demo(1,2,3)
print(obj) #abc should be (1+2)*3 = 9
print("\nchange a to 4")
obj.a = 4
print(obj) #abc should be (4+2)*3 = 18
print("\nchange b to 5")
obj.b = 5
print(obj) #abc should be (4+5)*3 = 27
print("\nchange c to 6")
obj.c = 5
print(obj) #abc should be (4+5)*6 = 54
产生以下输出
init
(1 + 2) * 3 = 9
change a to 4
(4 + 2) * 3 = 18
change b to 5
(4 + 5) * 3 = 27
change c to 6
(4 + 5) * 6 = 54
Process finished with exit code 0
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句