← Timeline
Avatar placeholder
tigra
A discussion about mutating default parameter values in Python

Anton Kulaga wrote:

There is one extremely annoying design flaw in Python. When you have a function with a list as a default argument, i.e.:

from typing import *

def foo(a: List = []) -> List:
a.append(1)
return a

a sane person would expect it to always return [1] (that how it works in most of the programming languages and how it must work), however, in Python the default value mutates each time one calls the function.

>>> foo()
[1]
>>> foo()
[1,1]
>>> foo()
[1,1,1]

I assume this is annoying side-effect is caused because Python evaluates default arguments at function definition time. Probably, it used to have some meaning when people wrote the interpreter (optimization or something else), but now it is just a common bug source

me:

I don't think it is grounded to expect that a default value will be initialized from scratch every time the function is called.

Anton Kulaga:

I think it is just common sense. foo() should be the same as foo([1]) if default is [1]. That what one typically expects.

me:

Then how should it be implemented inside?

  1. Calculate it every time even if it is a heavy expression?
  2. Or, before the call, check the stored default value equality to the first initialized value of it? So, expect __eq__() etc. implemented correctly for a class used to represent a default value?
  3. Or, initialize it first, store a copy (how deep copy?) and use the stored value every time the function is called?
  4. Or, somehow disable the side effects for methods that are called on object which is a default value for a parameter?

Options 2-4 would lead to more uncertainty when understanding how code works, 1 may be costly.

I think when you are modifying a mutable object which is passed as a parameter you are already on a slick ground and have to be extra careful.

If you want to be 100% safe from such troubles, one way would be to use immutable tuples instead of lists (at least as default values of parameters), or, use a pure functional language where all values are immutable :)

To react or comment  View in Web Client