Least Astonishment and the Mutable Default Argument

0 votes

Anyone tinkering with Python long enough has been bitten (or torn to pieces) by the following issue:

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

Python novices would expect this function to always return a list with only one element: [5]. The result is instead very different, and very astonishing (for a novice):

>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
>>> foo()
[5, 5, 5, 5]
>>> foo()                                                                                                               

Together with most of your comments and Utaal's in particular, I elaborated further:

>>> def a():
...     print("a executed")
...     return []
... 
>>>            
>>> def b(x=a()):
...     x.append(5)
...     print(x)
... 
a executed
>>> b()
[5]
>>> b()
[5, 5]

To me, it seems that the design decision was relative to where to put the scope of parameters: inside the function or "together" with it?

Doing the binding inside the function would mean that x is effectively bound to the specified default when the function is called, not defined, something that would present a deep flaw: the def line would be "hybrid" in the sense that part of the binding (of the function object) would happen at the definition, and part (assignment of default parameters) at function invocation time.

The actual behavior is more consistent: everything of that line gets evaluated when that line is executed, meaning at function definition.

Dec 17, 2020 in Python by Roshni
• 10,480 points
58 views

1 answer to this question.

0 votes

Actually, this is not a design flaw, and it is not because of internals, or performance.
It comes simply from the fact that functions in Python are first-class objects and not only a piece of code.

As soon as you get to think into this way, then it completely makes sense: a function is an object being evaluated on its definition; default parameters are a kind of "member data" and therefore their state may change from one call to the other - exactly as in any other object.

In any case, Effbot has a very nice explanation of the reasons for this behavior in Default Parameter Values in Python.
I found it very clear, and I really suggest reading it for a better knowledge of how function objects work.

answered Dec 17, 2020 by Gitika
• 65,910 points

Related Questions In Python

0 votes
1 answer

How can I find out the index of an element from row and column in Python?

You probably want to use np.ravel_multi_index: [code] import numpy ...READ MORE

answered Apr 16, 2018 in Python by charlie_brown
• 7,780 points
654 views
0 votes
1 answer

What's the difference in Qt between setVisible, setShown and show/hide

show() is just a convenience function for ...READ MORE

answered Apr 17, 2018 in Python by anonymous
4,571 views
0 votes
1 answer

What is the difference between list and tuple?

Lists are mutable(values can be changed) whereas ...READ MORE

answered May 4, 2018 in Python by aayushi
• 750 points
3,716 views
0 votes
2 answers
+1 vote
2 answers

how can i count the items in a list?

Syntax :            list. count(value) Code: colors = ['red', 'green', ...READ MORE

answered Jul 6, 2019 in Python by Neha
• 330 points

edited Jul 8, 2019 by Kalgi 2,161 views
0 votes
0 answers
0 votes
5 answers
0 votes
1 answer

Which will good platform to perform anaconda navigation or other and install the package on anaconda ide

Hey, @Daulat, We use Anaconda Navigator to launch ...READ MORE

answered Apr 8, 2020 in Python by Gitika
• 65,910 points
164 views