【发布时间】:2020-12-04 17:56:38
【问题描述】:
我正在使用 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)之类的吗?
【问题讨论】:
-
返回计算结果的
property不够吗? -
@snakecharmerb 谢谢你的灵感。实际上
hybrid_property成功了。
标签: python events sqlalchemy