Enter the void *

In Python, default values are evaluated at import time

by Etienne Millon on January 12, 2016

Tagged as: .

This is a minimal example reproducing a bug I found in html2text. Suppose we have configuration module, a library that uses the configuration, and a main function.

# config.py
default = False

# lib.py
import config

def f(x=config.default):
    print x

# main.py
import config
import lib

config.default = True
lib.f()

The main function sets the configuration, then calls f. One would expect that the program prints True… but it actually prints False.

This behavior can be surprising, but it is perfectly logical once you know the rule:

In Python, default values are evaluated at import time.

This is all there is to know about this problem. Here is what happens at runtime in the above example:

That last part is not only a metaphor, the default value is actually part of the function object:

>>> def f(x=3):
...     print x
...
>>> f.func_defaults
(3,)

In order to avoid this caveat, the usual solution is to use None for default values:

def f(x=None):
    if x is None:
        x = config.default
    print x

That way, the evaluation of config.default will happen at runtime, which is what we want here. The above program will indeed print True.