0

I am confused by the scope of the names argument used in following example

def disp( p1, list=[] ):
    list.append( p1 )
    return list 

list1 = disp( 10 )
list2 = disp( 123 )
list3 = disp( 'a' )

print ( list1 )
print ( list2 )
print ( list3 )

Output is

[10, 123, 'a']
[10, 123, 'a']
[10, 123, 'a']

How can we explain the scope of the variable list, which is the named argument in the function definition? Instead of a list, if it's something else, say integer, its works differently.

def disp2( p1, myVal = 0 ):
    myVal += myVal + p1 
    return myVal 

v1 = disp2(9)
v2 = disp2(7)
v3 = disp2(77)

print ( v1, v2, v3 )

Ideas? I want to understand the details behind the first example (its easy to avoid it, by changing the code ).

  • https://stackoverflow.com/questions/23029727/why-do-list-operations-in-python-operate-outside-of-the-function-scope – Benoit F Jul 17 '20 at 10:31

3 Answers3

1

In Python, some types are immutable (str, int, etc.) while others are mutable (list, dict, tuple, etc).

Your code behaves like that because you are setting the default argument as mutable type (list=[]), which in returns results in the same object but with different (updated) values (content).

This article might be a good reading to understand this behaviour and how to potentially solve it.

errata
  • 5,695
  • 10
  • 54
  • 99
0

Python’s default arguments are evaluated once when the function is defined, not each time the function is called. This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.

https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments

Vishal Singh
  • 6,014
  • 2
  • 17
  • 33
0

Well the default values get assigned once only,

And your not copying the list you just added another key variable to reach it so all of them are the same list in this case

so do this

def disp( p1, list = None ):
    if list is None: # None is nothing
        list = [] 
    list.append( p1 )
    return list 

# here you don't need to copy since there different lists
# unlike then
list1 = disp( 10 )
list2 = disp( 123 )
list3 = disp( 'a' )

print ( list1 )
print ( list2 )
print ( list3 )

The output will be

[ 10 ]
[ 123 ]
[ 'a' ]

You can copy lists like this

list = Original.copy() # now those will be fundamentally different lists but same values

Or like this

list = [i for i in Original]
12ksins
  • 307
  • 1
  • 12