computergorl
computergorl

Reputation: 153

Why does Python sometimes not create new objects for function arguments?

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

Answers (2)

fishsticks
fishsticks

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

Alex Jadczak
Alex Jadczak

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

Related Questions