80

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?

Joan Venge
  • 315,713
  • 212
  • 479
  • 689
  • 18
    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 Nov 29 '13 at 20:13
  • 5
    @NoobSaibot: The answers in the "duplicate" are a **lot** better. – Makoto Dec 28 '13 at 19:06
  • 1
    [This answer by Mark Ransom](http://stackoverflow.com/a/8140747/3061686) and [this blog by effbot on Python objects](http://effbot.org/zone/python-objects.htm) together will make things as clear as they can be. – akki Mar 05 '17 at 06:52
  • 2
    @Makoto that does not justify this first question being marked as duplicate. That encourages duplicating Answers. – cellepo Sep 28 '20 at 16:47
  • 1
    @cellepo: And my comment is deleted too.. Censorship too great job mods! – Joan Venge Oct 01 '20 at 04:42
  • The blog post is not available anymore. Appreciate SO for being here storing all the content. – esboych Dec 14 '22 at 07:35

8 Answers8

102

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.

superpupervlad
  • 122
  • 1
  • 8
Stephen
  • 4,176
  • 2
  • 24
  • 29
  • 19
    You first say "Python passes by reference", but then in the quoted text, it says "Python passes references-to-objects by value" -- which is not the same thing! Python is actually not call-by-reference at all, it's [call by sharing](http://effbot.org/zone/call-by-object.htm). – Daniel Pryden Jan 12 '12 at 18:48
  • 14
    Python does not pass by reference, as the term is typically understood (e.g. Pascal or C++). Assigning to the variable does *not* affect the caller in any way, and this is the case regardless of the data type involved. When calling functions, Python creates a new name for the same object, so that mutating the object is reflected in the caller, but assigning to the function-local variable is not. This is exactly the same mechanism as the one in Java or Lisp. Your answer unfortunately adds to the confusion. – user4815162342 Nov 27 '12 at 17:43
  • @user4815162342: just to be clear, assigning to the local variable in the function would create a new object which will be alive during the execution of the function and die when the function is exited. Correct? – vipulnj Jul 24 '17 at 17:54
  • @vipulnj Correct. Unless, of course, the object is stored in a global variable, in which case it will survive the function's exit - but it will still not affect the object seen by the caller. – user4815162342 Jul 25 '17 at 07:27
84

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.

nosklo
  • 217,122
  • 57
  • 293
  • 297
  • I have decided next time I am asked to explain this, I will use the id() function to show the binding of the name to the reference. – Tim Richardson Nov 11 '15 at 10:01
  • 1
    Names are references in the current scope. The only visible difference between "names" and "variables" (as in Java) is when you look at `locals()`, which most of the time you don't. And yes, Java has several types of primitives whereas Python has only one. – Elazar Sep 04 '16 at 23:04
  • 1
    That last sentence is a perfect summary of what I see many newbies of Python getting very confused with! – Tomerikoo Aug 18 '20 at 13:21
28

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.

shafee
  • 15,566
  • 3
  • 19
  • 47
cellepo
  • 4,001
  • 2
  • 38
  • 57
  • 1
    This is a longer version of the earlier answer http://stackoverflow.com/a/534389/2707864, worth posting. – sancho.s ReinstateMonicaCellio Jul 16 '15 at 07:20
  • @cellepo Your answer explains the behaviour but does not explain the reason for this behaviour. I mean what is the difference between a number within a list when passed as an argument; and an integer passed directly as an argument. Why is exactly that one integer changes and another does not? – IqbalHamid Jun 29 '21 at 16:31
  • @IqbalHamid why are you not treating me as nicely or respectfuly as [your other comment](https://stackoverflow.com/a/13009453/1357094) to a different answer here? Why aren't you asking them your questions also? I even provide more explanation than they do, for which you are asking me for more explanation... – cellepo Jun 30 '21 at 22:46
  • @celleppo. No disrespect intended. You've presented a fascinating observation. And one that python programmers need to be aware of. So thank you for bringing that to our attention. But my initial reading of your answer left me unclear why this behaviour occurs in python. You went on to highlight a distinction between the 2 scenarios. But I could not understand what it is about a list that makes it mutable. The other person's code said the same as your code but returning references provided extra clarity over what was happening and also how. No disrespect intended. Your ans still helpful – IqbalHamid Jul 01 '21 at 23:54
  • I never claimed to explain any reasoning to a level that caters to you personally; the Question did not ask for it. But my free Answer already has indeed had explanation for the reasoning - it is what already existed in bold at the top of my Answer - you can see in edit history that part is unchanged since before your first comment, which shows your lack of due diligence: Read more carefully, and research yourself to find your own answers for your personal preference of needs - at least attempt that, before criticizing my free advice (which already did what you are asking for). – cellepo Jul 03 '21 at 07:00
  • It is reflective of your position, that you have now deleted your other prior comment on a different Answer – cellepo Dec 29 '22 at 18:49
9

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

ChrisF
  • 134,786
  • 31
  • 255
  • 325
anthony
  • 40,424
  • 5
  • 55
  • 128
4

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

S.Lott
  • 384,516
  • 81
  • 508
  • 779
3

By reference:

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


>>> foo(x)
>>> x
[1, 1, 2, 3]
Harper Shelby
  • 16,475
  • 2
  • 44
  • 51
  • @Harper Shelby: Good, but risky example. Doesn't work for immutable objects like strings, tuples, ints, etc. – S.Lott Feb 10 '09 at 22:04
  • True, but it isn't because the immutable object are being passed by value, but rather because they are automatically copied on mutate. – Josh Heitzman Nov 14 '12 at 18:33
3

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.

Matt
  • 10,434
  • 1
  • 36
  • 45
1

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']

Antonio Leite
  • 460
  • 3
  • 7