Python Puzzle - Where Did The Time Go?
Written by Mike James   
Article Index
Python Puzzle - Where Did The Time Go?

A Python programming puzzle to get you up to speed. This one is all about time keeping, or is it? There are some strange things that go on in Python when you aren't paying attention. 


Python is a dynamic language and, while you can argue about terminology, its behavior tends toward what you would expect from an interpreter rather than a compiler in the sense that many things that you might expect to happen at compile time happen at run time. It is in the very nature of an interpreter-implemented language that compile time and run time tend to be confused. In this case the effect on the language is very unexpected.


Python functions are the workhorses of the language and knowing how to use them is all-important. One of the slightly more sophisticated features is the ability to define default values for parameters. 

For example, you could write something like:

def count(n=0):
   return n

Not a very inspiring function but it serves to demonstrate the idea. If you call count with an argument for n then count adds one to the current value:

print( count(m))

This instruction prints whatever is in m plus one - note it doesn't alter m. If you don't specify a value for n then the default value of 0 is used:

print( count())

In this case the argument for n isn't specified and so n is set equal to zero and the function continues. The result is, of course, that the function returns one. 

So far so good. 

If a function has a number of parameters then you can set defaults for all or any of them, but because the position of a parameter is used to identify it once you stop supplying parameters then defaults have to be used for the rest. 

For example, with the definition:

def demo(a,b,c=0,d=0):
   return a+b+c+d

you can call the function using:


in which case and c and d will be set to their defaults,


print(demo(1,2,3) )

when only d will use the default value.

Note there is no way you can specify d and let c take its default.

Similarly, you can't call the function using demo(1) because there is no default for b. 

It all works very well and default values for parameters can make functions easier to use.


As always the code presented as part of this puzzle is the stripped-down minimum necessary to make the problem show itself. In real code the problem would be much better hidden in the usual complexities and irrelevancies. 

One section of a bigger program needed to compute a time difference and the following function was created:

import time
def timediff(time2,time1):
   return time2-time1

Often time1 was simply the current time and so the function was being called using something like:


where eventTime is the time to subtract the current time from. 

Of course, an obvious simplification would be to set time1 to the current time if the supplied value was zero say and this was the first simplification of the function:

def timediff(time2,time1):
    if time1==0:
    return time2-time1


This worked perfectly when called using:


but then a more experienced Python programmer said "why not use a default value"? So it was altered to:

def timediff(time2,time1=time.time()):
    return time2-time1

a much simpler function that could be be called using:


So much more elegant - but it doesn't work!

If you try it the time differences returned seem to be very wrong. 

Once clue as to the problem (don't read if you don't want a hint):

when the function is called with eventTime set to the current time the result isn't zero and it increases as the current time increases. 

So what is wrong - how can time go astray?

It is all perfectly reasonable, but there is something not right at all.


Turn to the next page to find out the solution.