3

假设我有一个变量 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 的变量(是的,它是一个角色扮演游戏程序)。每当函数中使用的变量发生变化时,我希望 hitPoints 也发生变化。

4

2 回答 2

4

在 Python 中执行此操作的典型方法是使用class

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)
于 2012-04-22T07:30:59.593 回答
2

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()

很抱歉,我现在很累,无法完成这个示例。我也没有测试它。但这显示了一种跟踪值的方法,如果它们不同,则做不同的事情。你像这样使用它:

# 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_objects应该更新。我已经添加了代码来做到这一点。

现在我要睡觉了!

于 2012-04-22T08:08:18.153 回答