You can try something like this:
class Variable: def __init__(self, v): self.v=v self.command=None def set(self, v): self.v=v if self.command!=None: self.command() def get(self): return self.v def trace(self, command): self.command=command x=Variable(0) def money(): amount="{:.2f}".format(x.get()) print("You have $"+amount+".") x.trace(money) x.set(5.55) x.set(15.14)
If you need arguments, just use a lambda function. In light of that (and the accepted answer I more recently examined more thoroughly), here's a more complex version with comments, more functionality and examples:
class Variable: #This is a class for the variable you want to bind something to def __init__(self, v): self.v=v self.commands=[] def set(self, v): #Set the variable's value and call any bound functions self.v=v for x in self.commands: x() def get(self): #Get the variable's value return self.v def trace(self, *commands): #Bind one or more functions to the variable for x in commands: if x in self.commands: raise ValueError("You can’t add the same command object twice. If you need to, use another lambda function that calls the same function with the same parameters.") self.commands.extend(commands) def untrace(self, *commands): #Unbind one or more functions from the variable for x in commands: if x not in self.commands: raise ValueError(str(x)+" is not a traced command.") for x in commands: if x in self.commands: self.commands.remove(x) def clear_traces(self): #Removes all functions bound to the variable self.commands.clear() x=Variable(0) #Make the variable, starting with a value of 0 def money(name): #Define the method to bind amount="{:.2f}".format(x.get()) print(name+" has $"+amount+".") sam=lambda : money("Sam") #We're making a new method to bind that calls the old one with the argument "Sam" sally=lambda : money("Sally") #Another one (Sally and Sam will always have the same amount of money while they are both bound to the variable.) #Bind them both to the value (not that this is practical, but we're doing both for demonstration) x.trace(sam) x.trace(sally) #Set the value x.set(5.55) #Unbind the sam lambda function and set the value again x.untrace(sam) x.set(15.14) """ This prints the following: > Sam has $5.55. > Sally has $5.55. > Sally has $15.14. """
Alternative
Anyway, you can also use the built-in functionality that comes with Tkinter, with such as DoubleVar.trace() or someWidget.wait_variable().
The trace() method allows you to bind a method to a StringVar, IntVar, FloatVar, DoubleVar, BooleanVar or such variables. Here's a full working Python 3.x example:
from tkinter import * tk=Tk() tk.withdraw() d=DoubleVar(master=tk, value=0) def my_event_handler(*args): amount="{:.2f}".format(d.get()) print("$"+amount) d.trace(mode="w", callback=my_event_handler) d.set(5.55) d.set(15.12) """ This prints the following: > You have $5.55. > You have $15.12. """
You may want to destroy the Tk object at the end of the program. It seems to exit fine without it in my example, however.
wait_variable() is another alternative that causes the calling function to halt without halting your GUI until a variable you specified changes. There are other similar methods, too.