在Python中,我可以将变量绑定到函数/表达式以便它自动更新吗?
假设我有一个变量a,它是一个函数/表达式F的结果,而F又有很多其他变量,比如X,Y和Z 是否可以将A绑定到F,以便在X、Y或Z发生变化时,A将自动更新 我想避免的是,每次X、Y和Z发生变化时,我都必须记住在代码中显式地更新A。我也不想每次使用A时都调用这个函数 示例(根据请求):我有以下函数:在Python中,我可以将变量绑定到函数/表达式以便它自动更新吗?,python,Python,假设我有一个变量a,它是一个函数/表达式F的结果,而F又有很多其他变量,比如X,Y和Z 是否可以将A绑定到F,以便在X、Y或Z发生变化时,A将自动更新 我想避免的是,每次X、Y和Z发生变化时,我都必须记住在代码中显式地更新A。我也不想每次使用A时都调用这个函数 示例(根据请求):我有以下函数: def calcHits(): return sum(hitDiceRolls,level*modList['con']) 在我的程序中(函数之外),我有一个变量叫做hitPoints(是的,
def calcHits():
return sum(hitDiceRolls,level*modList['con'])
在我的程序中(函数之外),我有一个变量叫做hitPoints(是的,这是一个角色扮演游戏程序)。每当函数中使用的变量发生变化时,我希望命中点也发生变化。在Python中实现这一点的典型方法是使用
类
:
class ExpressionBinder:
def __init__(self, f):
self.f = f
self.x = 0
self.y = 0
self.z = 0
@property
def result(self):
return self.f(self.x, self.y, self.z)
您可以这样使用它:
def f(x, y, z):
return x**3 + y**2 + z
b = ExpressionBinder(f)
b.x = 1
b.y = 2
b.z = 3
print(b.result)
# want to track x, y, z
trk = Trk(x, y, z)
trk.fn() # returns up-to-date value
trk.x = new_value
trk.fn() #detects that trk.x changed and computes new trk.value
Python中没有办法自动在全局或局部范围内重新绑定一个名称,以响应正在恢复的其他名称。但是,应该可以创建一个可以跟踪某些值的类,并具有一个返回您调用的
a
值的成员函数。而且,正如@Alok指出的,您可以使用属性描述符生成隐式调用函数以返回其值的成员名称,因此您可以隐藏函数并将该名称视为普通的旧名称
class Trk(object):
"""Track some values and compute a function if any change"""
def __init__(self, name, fn, **objects_to_track):
def _trk_fn(self):
if any(self.__dict__[x] != self.original_objects[x] for x in self.original_objects):
self.value = self.saved_fn(self.__dict___)
# now that self.value is updated, also update self.original_objects
for x in self.original_objects:
self.original_objects[x] = self.__dict__[x]
return self.value
self.original_objects = objects_to_track # make reference copy
self.__dict__.update(objects_to_track)
self.name = name
self.saved_fn = fn
self.fn = self._trk_fn()
self.value = self.fn()
很抱歉,我现在很累,我不能完成这个例子。我也没有测试它。但这显示了一种跟踪值的方法,如果它们不同,就做些不同的事情。您可以这样使用它:
def f(x, y, z):
return x**3 + y**2 + z
b = ExpressionBinder(f)
b.x = 1
b.y = 2
b.z = 3
print(b.result)
# want to track x, y, z
trk = Trk(x, y, z)
trk.fn() # returns up-to-date value
trk.x = new_value
trk.fn() #detects that trk.x changed and computes new trk.value
如果上述方法有效,您可以使用属性描述符绑定名称,以便尝试从名称中读取值时调用self.fn()
编辑:哦,当更新self.value
时,应该更新self.original\u对象,这一点很重要。我添加了代码来实现这一点
现在我要睡觉了 你需要举一个例子,你能用这样的东西吗?我一直在看,它会起作用的。在这种情况下,我将编写代码来更新类的setter部分中的相关变量。谢谢。我也喜欢发送实际函数的优雅(这使得它非常动态)。每次我不想使用结果值时,它仍然会拉取结果,但我猜这是当前唯一的解决方案。如果函数运行成本很高,您可以缓存结果,并且只有在输入值自上次运行以来发生更改时才重新计算结果。是的,我必须检查一下。谢谢哇,我不知道@property
!那很有用。