Default Parameter Values in Python

3230
1
09-03-2015 12:38 PM

Default Parameter Values in Python

Any new Python analyst should be able to tell you what the following would return:

def foo(a=[]):
  a.append(5)
  return a
def main():
  foo()
  foo()
  foo()

if __name__ == "__main__":
  main()



The new python analyst would expect the end result to be an array containing one item, 5. This however is not the case (see attached file). It instead returns an array of three 5's.

This may seem like an internal mistake in the Python language but it is as designed. Default parameter vales are always evaluated when, and only when, the def statement they belong to is executed (defined). This means that these default parameter values are created and stored in memory for future access as a new function object when the code is first executed. Successive calls to that function do not evaluate the def call again, so the default arguments do not change.

Why is this important?

If using mutable objects such as polygons in default parameter initialization, you may over time return different results than what you expected to return and can create bad output or geometries.

These sources may be able to provide an explanation as to why this happens:

Default Parameter Values in Python
http://effbot.org/zone/default-values.htm

“Least Astonishment” in Python: The Mutable Default Argument
http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument

Common Gotchas
http://docs.python-guide.org/en/latest/writing/gotchas/

Comments
DanPatterson_Retired
MVP Emeritus

Alexander

Interesting warning, which is why you should use bar if foo is not the desired behaviour

def bar(b=[]):
    if b:
        b.append(4)
        print("never gets here {}".format(b))
    else:
        b=[]
        print("empty list in.{}".format(b))
        b.append(4)
        print("now has ... {}".format(b))
    
def main():  
    print("\nnow for something completely different\n")
    bar()
    bar()
    bar()
  
if __name__ == "__main__":  
    main()
    del bar

results in

now for something completely different
empty list in.[]
now has ... [4]
empty list in.[]
now has ... [4]
empty list in.[]
now has ... [4]
Version history
Last update:
‎12-12-2021 03:42 AM
Updated by: