Reputation: 153
I assumed that whenever you passed an object into a function, it automatically created a separate copy for you that you could modify without changing the original. However, the following code terminates with this error every time.
>>> testvar = ['a' for a in range(100000)]
>>> def func(arg):
while arg is testvar:
arg.pop()
>>> func(testvar)
Traceback (most recent call last):
File "<pyshell#47>", line 1, in <module>
thing(m)
File "<pyshell#43>", line 3, in thing
obj.pop()
IndexError: pop from empty list
Upvotes: 0
Views: 95
Reputation: 753
"I assumed that whenever you passed an object into a function, it automatically created a separate copy for you that you could modify without changing the original."
Well, your assumption there is wrong. Variables are passed by reference, not value. This includes if you set a default value for an argument to an empty list, and change it in the function, the next time you try to use that default value, it won't be an empty list anymore.
def foo(bar=[]):
bar.append("baz")
foo()
foo()
# bar is now ["baz", "baz"]
Upvotes: 2
Reputation: 582
from: https://docs.python.org/3.4/library/copy.html
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other. This module provides generic shallow and deep copy operations (explained below).
when you are calling your function, you are doing the following:
func(arg=testvar)
If you want to have an actual copy of your data you could modify your function to the following:
def func(arg):
arg_copy = arg[:]
# mutate arg_copy here without mutating arg
Upvotes: 2