In Python, can I bind a variable to a function / expression so that it automatically updates?

Say I have a variable A, which is the result of a function / expression F. In its turn, it has a number of other variables, say X, Y and Z.

Is it possible to associate A with F so that with every change, X, Y or ZA is automatically updated?

What I want to avoid is that every time X, Y and Z change, I must remember to explicitly update the code in the code. I also do not want to call a function every time I want to use A.

Example (by request): I have the following function:

def calcHits():
    return sum(hitDiceRolls,level*modList['con']) 

and in my program (outside the function) I have a variable called hitPoints (yes, this is a role-playing game program). Whenever the variables used in a function change, I want hitPoints to change as well.

+3
source share
2 answers

In Python, there is no way to automatically rewrite a name in a global or local area in response to bounces of other names. However, it should be possible to create a class that can track some values ​​and have a member function that returns the value you called A. And, as @Alok noted, you can use property descriptors to create a member name that implicitly calls a function to return its value, so you can hide this function and treat the name as a plain old name.

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

Sorry, but I am very tired right now and I can not finish this example. I did not check either. But this shows one way to track values, and if they are different, do something else. You use it as follows:

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

EDIT: , , self.value, self.original_objects . .

!

+2

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)
+4

All Articles