73
votes

When you pass a collection like list, array to another function in python, does it make a copy of it, or is it just a pointer?

8
This question was asked in Feb. '09, while the "original" question was asked in June of that year. Why is this one the duplicate?Noob Saibot
@NoobSaibot: The answers in the "duplicate" are a lot better.Makoto
This answer by Mark Ransom and this blog by effbot on Python objects together will make things as clear as they can be.akki
@Makoto that does not justify this first question being marked as duplicate. That encourages duplicating Answers.cellepo
@cellepo: And my comment is deleted too.. Censorship too great job mods!Joan Venge

8 Answers

89
votes

Python passes references-to-objects by value.

Python passes references-to-objects by value (like Java), and everything in Python is an object. This sounds simple, but then you will notice that some data types seem to exhibit pass-by-value characteristics, while others seem to act like pass-by-reference... what's the deal?

It is important to understand mutable and immutable objects. Some objects, like strings, tuples, and numbers, are immutable. Altering them inside a function/method will create a new instance and the original instance outside the function/method is not changed. Other objects, like lists and dictionaries are mutable, which means you can change the object in-place. Therefore, altering an object inside a function/method will also change the original object outside.

75
votes

Thing is, the whole reference/value concept won't fit into python. Python has no "value" of a variable. Python has only objects and names that refer to objects.

So when you call a function and put a "name" inside the parenthesis, like this:

def func(x): # defines a function that takes an argument
    ... # do something here

func(myname) # calling the function

The actual object that myname is pointing is passed, not the name myname itself. Inside the function another name (x) is given to refer to the same object passed.

You can modify the object inside the function if it is mutable, but you can't change what the outside name is pointing to. Just the same that happens when you do

anothername = myname

Therefore I can answer your question with:

it is "pass by value" but all values are just references to objects.

26
votes

Answers here have been helpful, but I find the need to exhibit this fine distinction which I haven't seen covered, which I've proven to myself with the subsequent CL experiment:

  1. An immutable object ALONE CANNOT be changed within a function call. (answers so far have said that much...)
  2. BUT, an immutable object CONTAINED WITHIN a mutable object CAN be re-assigned within a method call.

'num' does not change here because it is an immutable Number object [supports my point 1.]:

def incr_num(num):
    num += 1

num = 0

num
0

incr_num(num)

num
0

'list[0]' here is an immutable Number object also.

def incr_list(list):
    list[0] += 1

list = [0]

list[0]
0

incr_list(list)

list[0]
1

So how did 'list[0]', being an immutable Number object, change (supports my point 2.) while the above example's Number object 'num' did not? The immutable Number object 'list[0]' is contained within the mutable list object 'list', while 'num' from the 1st example is just a non-contained Number object (immutable).

Although well-intended, I feel @Stephen Pape top-rated answer (quoted below), and some other similar ones, were not totally correct (and that motivated me to write this answer):

Some objects, like strings, tuples, and numbers, are immutable. Altering them inside a function/method will create a new instance and the original instance outside the function/method is not changed.

My 2nd code experiment above shows a Number object ('list[0]') being altered within a method, and then the original instance outside the function changed.

7
votes

A reference is passed, but if the parameter is an immutable object, modifying it within the method will create a new instance.

4
votes

The object is passed. Not a copy, but a reference to the underlying object.

3
votes

I would also recommend looking at the copy module:

Python documentation for copy

It will help you to understand the underlying issues and how to use it to perform your own deep copy.

2
votes

By reference:

>>> x = [0,1,2,3]
>>> def foo(x_list):
    x_list[0] = 1


>>> foo(x)
>>> x
[1, 1, 2, 3]
1
votes

Please let me give a humble example

def swap(a, b):
    x = a
    print id(x)
    print id(a)
    print id(b)
    a = b

    print id(a)
    b = x
    print id(b)
    a[0]= '20'




var1 = ['1','2','3','4']
var2 = ['5','6','7','8','9']
print id(var1)
print id(var2)

swap(var1, var2)

print id(var1)
print id(var2)
print var1
print var2

which produces the following result

28329344 var1 28331264 var2 28329344 x 28329344 a 28331264 b After a = b 28331264 a after b = x 28329344 b after return 28329344 var1 28331264 var2 ['1', '2', '3', '4'] ['20', '6', '7', '8', '9']

Mapping to the memory addresses 28329344 28331264 var1 var2 a b x After a=b a After b=x b After a[0] = '20' [0] = '20' After return ['1','2','3','4'] ['20', '6', '7', '8', '9']