in productionthis code should definitely have extra documentation using docstringsthe call_after method should at least mention that the delay parameter is in secondsand that the callback function should accept one argumentthe timer doing the calling we have two classes here the timedevent class is not really meant to be accessed by other classesall it does is store endtime and callback we could even use tuple or namedtuple herebut as it is convenient to give the object behavior that tells us whether or not the event is ready to runwe use class instead the timer class simply stores list of upcoming events it has call_after method to add new event this method accepts delay parameter representing the number of seconds to wait before executing the callbackand the callback function itselfa function to be executed at the correct time this callback function should accept one argument the run method is very simpleit uses generator expression to filter out any events whose time has comeand executes them in order the timer loop then continues indefinitelyso it has to be interrupted with keyboard interrupt (ctrl or ctrl breakwe sleep for half second after each iteration so as to not grind the system to halt the important things to note here are the lines that touch callback functions the function is passed around like any other object and the timer never knows or cares what the original name of the function is or where it was defined when it' time to call the functionthe timer simply applies the parenthesis syntax to the stored variable here' set of callbacks that test the timerfrom timer import timer import datetime def format_time(message*args)now datetime datetime now(strftime("% :% :% "print(message format(*argsnow=now)def one(timer)format_time("{now}called one"def two(timer)format_time("{now}called two"def three(timer)