Passing values in Python [duplicate]
Asked Answered
G

8

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?

Grommet answered 10/2, 2009 at 21:51 Comment(6)
This question was asked in Feb. '09, while the "original" question was asked in June of that year. Why is this one the duplicate?Downey
@NoobSaibot: The answers in the "duplicate" are a lot better.Valise
This answer by Mark Ransom and this blog by effbot on Python objects together will make things as clear as they can be.Consalve
@Valise that does not justify this first question being marked as duplicate. That encourages duplicating Answers.Paschal
@cellepo: And my comment is deleted too.. Censorship too great job mods!Grommet
The blog post is not available anymore. Appreciate SO for being here storing all the content.Tithonus
F
103

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.

Felicitasfelicitate answered 10/2, 2009 at 21:53 Comment(4)
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.Lamarckism
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.Coiffure
@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?Matty
@Matty 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.Coiffure
I
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.

Isosceles answered 10/2, 2009 at 22:29 Comment(3)
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.Aldarcie
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.Larhondalari
That last sentence is a perfect summary of what I see many newbies of Python getting very confused with!Electrodynamic
P
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.

Paschal answered 27/11, 2012 at 6:8 Comment(6)
This is a longer version of the earlier answer https://mcmap.net/q/37849/-passing-values-in-python-duplicate, worth posting.Runt
@Paschal 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?Goddamned
@Goddamned why are you not treating me as nicely or respectfuly as your other comment 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...Paschal
@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 helpfulGoddamned
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).Paschal
It is reflective of your position, that you have now deleted your other prior comment on a different AnswerPaschal
P
10

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

Pinnatiped answered 10/2, 2009 at 21:54 Comment(0)
R
4

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

Recommit answered 10/2, 2009 at 21:53 Comment(1)
However, you also need to know when Python creates a new object, and when it dereferences.Aldarcie
H
3

By reference:

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


>>> foo(x)
>>> x
[1, 1, 2, 3]
Homily answered 10/2, 2009 at 21:55 Comment(2)
@Harper Shelby: Good, but risky example. Doesn't work for immutable objects like strings, tuples, ints, etc.Recommit
True, but it isn't because the immutable object are being passed by value, but rather because they are automatically copied on mutate.Rabbit
H
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.

Hornbeam answered 10/2, 2009 at 21:58 Comment(0)
J
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']
Jermainejerman answered 22/10, 2012 at 10:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.