Python Puzzle - Where Did The Time Go
Written by Alex Armstrong   
Article Index
Python Puzzle - Where Did The Time Go
Solution

Solution

OK - the problem is nothing to do with time keeping!

The same behavior could be demonstrated if almost any function was used to supply a default value in the same way. There are even problems if the default value is any mutable datatype, but that is another puzzle. 

The reason for the difficulty is that the function defaults are computed at the time the function is defined - not when it is called. 

So the default value for time1 is set when the Python interpreter reaches the definition of the function; not when the program calls the function.

This has two effects. The first is that the default value isn't set to the current time but the time when the function is defined. The second is that the apparent current time never changes. 

If you don't believe me try:

print( timediff(0))
print( timediff(0))
print( timediff(0))
print( timediff(0))

and you will see the same time value printed four times. 

This behavior often seems very strange to programmers familiar with other languages but most compiled languages have rules for what sorts of expressions you can use as default values and initial values.  These rules tend to come down to the simple requirement that the expression has to be fully determined at compile time. For Python compile time translates to definition time - hence the behavior. 

To be clear - the time.time() function is only called when timediff is defined i.e. when the Python interpreter reaches:

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

When this happens the value of the expression i.e. the function is stored and used as the default value for time1 every time timediff is called without a specified value for time1. 

This is not a bug it is how Python 2 and 3 are supposed to behave. 

Pattern

So what is the solution?

The main thing you need to be aware of is that initialization and default values aren't always determined at run time.

in this specific case you could simply revert to an earlier version of the function and avoid the use of default values:

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

This always works, but it isn't as convenient to use because you always have to specify a value for time1 even if it is a dummy. 

A better, and slightly more subtle, solution makes use of the default value as a flag to detect when the parameter needs dynamic initialization. 

For example a simple change to the previous version:

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

Now you can call timediff with time1 not specified and have a dynamic default value set at run time. 

Of course this depends on zero being a suitable flag for the missing argument - i.e. zero isn't going to be a valid time. More generally you can use None to indicate that a value is missing. For example:

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

You can always use None as a flag for a missing argument that needs dynamic initialization. 

The rule is:

  • always do dynamic defaults inside the function so that they are applied at run time. 

If you think that the troubles of default values are now all solved, the bad news is that there are other ways things can good wrong in what seem like very odd ways. But, as already mentioned, this is another puzzle. 

 

Banner

More Puzzles

Java
Strings and things

When are two strings equal? It sounds like an easy question but it's much more difficult when objects enter the picture as this Java brain-teaser demonstrates.


Sharpen Your Coding Skills
The Best Sub-Array Problem

At first glance this puzzle seems trivial, all you have to do is find a sub-array, in an array of numbers,  that sums to the largest value. It sounds almost too easy to need a solution, let alone [ ... ]


PHP
The Missing PHP Global

A global variable is a global variable and that's all there is to it. But if you write PHP code to be used by other people, you might want to consider that this isn't always the case. Can you see wher [ ... ]


Other Articles

 



 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.