How do I pass a variable by reference?

1,756,123

Solution 1

Arguments are passed by assignment. The rationale behind this is twofold:

  1. the parameter passed in is actually a reference to an object (but the reference is passed by value)
  2. some data types are mutable, but others aren't

So:

  • If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart's delight, but if you rebind the reference in the method, the outer scope will know nothing about it, and after you're done, the outer reference will still point at the original object.

  • If you pass an immutable object to a method, you still can't rebind the outer reference, and you can't even mutate the object.

To make it even more clear, let's have some examples.

List - a mutable type

Let's try to modify the list that was passed to a method:

def try_to_change_list_contents(the_list):
    print('got', the_list)
    the_list.append('four')
    print('changed to', the_list)

outer_list = ['one', 'two', 'three']

print('before, outer_list =', outer_list)
try_to_change_list_contents(outer_list)
print('after, outer_list =', outer_list)

Output:

before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']

Since the parameter passed in is a reference to outer_list, not a copy of it, we can use the mutating list methods to change it and have the changes reflected in the outer scope.

Now let's see what happens when we try to change the reference that was passed in as a parameter:

def try_to_change_list_reference(the_list):
    print('got', the_list)
    the_list = ['and', 'we', 'can', 'not', 'lie']
    print('set to', the_list)

outer_list = ['we', 'like', 'proper', 'English']

print('before, outer_list =', outer_list)
try_to_change_list_reference(outer_list)
print('after, outer_list =', outer_list)

Output:

before, outer_list = ['we', 'like', 'proper', 'English']
got ['we', 'like', 'proper', 'English']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'English']

Since the the_list parameter was passed by value, assigning a new list to it had no effect that the code outside the method could see. The the_list was a copy of the outer_list reference, and we had the_list point to a new list, but there was no way to change where outer_list pointed.

String - an immutable type

It's immutable, so there's nothing we can do to change the contents of the string

Now, let's try to change the reference

def try_to_change_string_reference(the_string):
    print('got', the_string)
    the_string = 'In a kingdom by the sea'
    print('set to', the_string)

outer_string = 'It was many and many a year ago'

print('before, outer_string =', outer_string)
try_to_change_string_reference(outer_string)
print('after, outer_string =', outer_string)

Output:

before, outer_string = It was many and many a year ago
got It was many and many a year ago
set to In a kingdom by the sea
after, outer_string = It was many and many a year ago

Again, since the the_string parameter was passed by value, assigning a new string to it had no effect that the code outside the method could see. The the_string was a copy of the outer_string reference, and we had the_string point to a new string, but there was no way to change where outer_string pointed.

I hope this clears things up a little.

EDIT: It's been noted that this doesn't answer the question that @David originally asked, "Is there something I can do to pass the variable by actual reference?". Let's work on that.

How do we get around this?

As @Andrea's answer shows, you could return the new value. This doesn't change the way things are passed in, but does let you get the information you want back out:

def return_a_whole_new_string(the_string):
    new_string = something_to_do_with_the_old_string(the_string)
    return new_string

# then you could call it like
my_string = return_a_whole_new_string(my_string)

If you really wanted to avoid using a return value, you could create a class to hold your value and pass it into the function or use an existing class, like a list:

def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
    new_string = something_to_do_with_the_old_string(stuff_to_change[0])
    stuff_to_change[0] = new_string

# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)

do_something_with(wrapper[0])

Although this seems a little cumbersome.

Solution 2

The problem comes from a misunderstanding of what variables are in Python. If you're used to most traditional languages, you have a mental model of what happens in the following sequence:

a = 1
a = 2

You believe that a is a memory location that stores the value 1, then is updated to store the value 2. That's not how things work in Python. Rather, a starts as a reference to an object with the value 1, then gets reassigned as a reference to an object with the value 2. Those two objects may continue to coexist even though a doesn't refer to the first one anymore; in fact they may be shared by any number of other references within the program.

When you call a function with a parameter, a new reference is created that refers to the object passed in. This is separate from the reference that was used in the function call, so there's no way to update that reference and make it refer to a new object. In your example:

def __init__(self):
    self.variable = 'Original'
    self.Change(self.variable)

def Change(self, var):
    var = 'Changed'

self.variable is a reference to the string object 'Original'. When you call Change you create a second reference var to the object. Inside the function you reassign the reference var to a different string object 'Changed', but the reference self.variable is separate and does not change.

The only way around this is to pass a mutable object. Because both references refer to the same object, any changes to the object are reflected in both places.

def __init__(self):         
    self.variable = ['Original']
    self.Change(self.variable)

def Change(self, var):
    var[0] = 'Changed'

Solution 3

I found the other answers rather long and complicated, so I created this simple diagram to explain the way Python treats variables and parameters. enter image description here

Solution 4

It is neither pass-by-value or pass-by-reference - it is call-by-object. See this, by Fredrik Lundh:

http://effbot.org/zone/call-by-object.htm

Here is a significant quote:

"...variables [names] are not objects; they cannot be denoted by other variables or referred to by objects."

In your example, when the Change method is called--a namespace is created for it; and var becomes a name, within that namespace, for the string object 'Original'. That object then has a name in two namespaces. Next, var = 'Changed' binds var to a new string object, and thus the method's namespace forgets about 'Original'. Finally, that namespace is forgotten, and the string 'Changed' along with it.

Solution 5

Think of stuff being passed by assignment instead of by reference/by value. That way, it is always clear, what is happening as long as you understand what happens during the normal assignment.

So, when passing a list to a function/method, the list is assigned to the parameter name. Appending to the list will result in the list being modified. Reassigning the list inside the function will not change the original list, since:

a = [1, 2, 3]
b = a
b.append(4)
b = ['a', 'b']
print a, b      # prints [1, 2, 3, 4] ['a', 'b']

Since immutable types cannot be modified, they seem like being passed by value - passing an int into a function means assigning the int to the function's parameter. You can only ever reassign that, but it won't change the original variables value.

Share:
1,756,123
David Sykes
Author by

David Sykes

Updated on July 08, 2022

Comments

  • David Sykes
    David Sykes almost 2 years

    Are parameters are passed by reference or value? How do I pass by reference so that the code below outputs 'Changed' instead of 'Original'?

    class PassByReference:
        def __init__(self):
            self.variable = 'Original'
            self.change(self.variable)
            print(self.variable)
    
        def change(self, var):
            var = 'Changed'
    
    • PhilS
      PhilS almost 15 years
      For a short explanation/clarification see the first answer to this stackoverflow question. As strings are immutable, they won't be changed and a new variable will be created, thus the "outer" variable still has the same value.
    • Ethan Furman
      Ethan Furman over 12 years
      The code in BlairConrad's answer is good, but the explanation provided by DavidCournapeau and DarenThomas is correct.
    • lqc
      lqc over 11 years
      Before reading the selected answer, please consider reading this short text Other languages have "variables", Python has "names". Think about "names" and "objects" instead of "variables" and "references" and you should avoid a lot of similar problems.
    • robert
      robert over 9 years
      another workaround is to create a wrapper 'reference' like this: ref = type('', (), {'n':1}) stackoverflow.com/a/1123054/409638
    • Terry Jan Reedy
      Terry Jan Reedy over 8 years
      For global names, pass by reference can be simulated by passing the name as a string and using globals(). def change(s): globals()[s] = 'changed' followed by a = 'orig'; change('a'); print(a) prints 'changed'.
    • MrRolling
      MrRolling almost 8 years
      Some immutable types: {int, float, long, complex, str, bytes, tuple, frozen set} Some mutable types: {byte array, list, set, dict}
    • Elazar
      Elazar over 7 years
      Python has variables. There's no conceptual problem with this term at all, and it is in common use.
    • akki
      akki about 7 years
      jeff Knupp's blog and stupidpythonideas are some good explanations for this.
    • gseattle
      gseattle over 4 years
      For the dataframe named 'bob' (from a string variable, and that's the tricky part), give me its current contents. Should be easy. Sadly I'm not getting it.
    • Abraham Sangha
      Abraham Sangha about 4 years
    • Ray Hulha
      Ray Hulha almost 4 years
      New official how of Iqc's link: david.goodger.org/projects/pycon/2007/idiomatic/…
    • Naren
      Naren about 3 years
      I come from C# & am trying to understand the question better. In Python everything is an object and objects can be mutable or immutable. The code here uses "string" which is an immutable object and attempting to change it within function scope is not going to change caller's value (behaves like pass-by-value) & if the code used a mutable custom class object - changing within function scope will change the caller's value (behaves like pass-by-ref). You'll see the exact same end result in C# (but the way it achieves is pass-by-value/ref). So isn't the net effect same? so isn't the question moot?
    • KulaGGin
      KulaGGin about 3 years
      @PeterR because OOP > 70s programming without classes and objects. It's just easier to write and understand programs when it's object-oriented. I think everything in the Universe can be represented as an object, even non-existing in real life programming concepts.
    • juanpa.arrivillaga
      juanpa.arrivillaga over 2 years
      @Naren no, it doesn't behave like either call by reference or call by value. Assignment to a parameter, regardless of the type used, will never be seen in the caller, therefore it is not call by reference. Similarly, objects are not copied, again, regardless of the type used, when they are passed in to a function, that is why mutator methods will affect those objects everywhere they are referenced.
  • Andrea Ambu
    Andrea Ambu almost 15 years
    Then the same is in C, when you pass "by reference" you're actually passing by value the reference... Define "by reference" :P
  • Marc Stober
    Marc Stober almost 15 years
    I'm not sure I understand your terms. I've been out of the C game for a while, but back when I was in it, there was no "pass by reference" - you could pass things, and it was always pass by value, so whatever was in the parameter list was copied. But sometimes the thing was a pointer, which one could follow to the piece of memory (primitive, array, struct, whatever), but you couldn't change the pointer that was copied from the outer scope - when you were done with the function, the original pointer still pointed to the same address. C++ introduced references, which behaved differently.
  • stoic_monk
    stoic_monk almost 15 years
    @andrea, not it is not like C at all. Conrad is correct, but the terms reference/values are confusing in python. That's why you should really use another term (see my link to effbot for a good explanation)
  • Zac Bowling
    Zac Bowling over 13 years
    bring up mutability is just adding confusion. it actually doesn't have anything to with the issue. you state it correct at first in that you can change the reference for something not in your scope (like a pointer pointer).
  • Cam Jackson
    Cam Jackson over 12 years
    @Zac Bowling Mutability is totally relevant. If strings were mutable, then the first string example would have a different output. It's important to know that setting the value of a passed-in string will create a new string object, not modify the passed one. Mutability is what prevents a string argument from behaving the same as say, an integer argument in this case.
  • Zac Bowling
    Zac Bowling over 12 years
    @Cam Jackson actually it's not relevant. Passing by reference means giving the ability to change the pointer that the calling reference was using. Talking about changing the data the destination of that pointer adds confusion and just an implementation detail.
  • Cam Jackson
    Cam Jackson over 12 years
    @Zac Bowling I don't really get how what you're saying is relevant, in a practical sense, to this answer. If a Python newcomer wanted to know about passing by ref/val, then the takeaway from this answer is: 1- You can use the reference that a function receives as its arguments, to modify the 'outside' value of a variable, as long as you don't reassign the parameter to refer to a new object. 2- Assigning to an immutable type will always create a new object, which breaks the reference that you had to the outside variable.
  • Mark Ransom
    Mark Ransom over 12 years
    @CamJackson, you need a better example - numbers are also immutable objects in Python. Besides, wouldn't it be true to say that any assignment without subscripting on the left side of the equals will reassign the name to a new object whether it is immutable or not? def Foo(alist): alist = [1,2,3] will not modify the contents of the list from the callers perspective.
  • Mark Ransom
    Mark Ransom over 12 years
    @BlairConrad, passing "by reference" in C is just a commonly recognized convention whereby you pass the pointer to something rather than the value of something. In that respect it behaves exactly like Python: you may update the value pointed to by the pointer but updating the pointer itself has no effect outside the function, since the pointer was passed by value.
  • Cam Jackson
    Cam Jackson over 12 years
    Good succinct explanation. Your paragraph "When you call a function..." is one of the best explanations I've heard of the rather cryptic phrase that 'Python function parameters are references, passed by value.' I think if you understand that paragraph alone, everything else kind of just makes sense and flows as a logical conclusion from there. Then you just have to be aware of when you're creating a new object and when you're modifying an existing one.
  • John Doe
    John Doe over 12 years
    Cue the sys._getframe(1).f_locals['new_string'] = 'foo' hack. Or just using ctypes.. :)
  • Luciano
    Luciano over 12 years
    I find it hard to buy. To me is just as Java, the parameters are pointers to objects in memory, and those pointers are passed via the stack, or registers.
  • stoic_monk
    stoic_monk over 12 years
    This is not like java. One of the case where it is not the same is immutable objects. Think about the trivial function lambda x: x. Apply this for x = [1, 2, 3] and x = (1, 2, 3). In the first case, the returned value will be a copy of the input, and identical in the second case.
  • Ethan Furman
    Ethan Furman over 12 years
    -1. The code shown is good, the explanation as to how is completely wrong. See the answers by DavidCournapeau or DarenThomas for correct explanations as to why.
  • Johan Lundberg
    Johan Lundberg over 12 years
    "..., but if you rebind the reference in the method, the outer scope will know nothing about it, and after you're done, the outer reference will still point at the original object." This is wrong or at least not relevant - you can never rebind a reference.
  • Kashif
    Kashif about 12 years
    But how can you reassign the reference? I thought you can't change the address of 'var' but that your string "Changed" was now going to be stored in the 'var' memory address. Your description makes it seem like "Changed" and "Original" belong to different places in memory instead and you just switch 'var' to a different address. Is that correct?
  • Mark Ransom
    Mark Ransom about 12 years
    @Glassjawed, I think you're getting it. "Changed" and "Original" are two different string objects at different memory addresses and 'var' changes from pointing to one to pointing to the other.
  • pepr
    pepr over 11 years
    The problem is that the assignment does something else than you expect. The list = [1, 2, 3] causes reusing the list name for something else and forgeting the originally passed object. However, you can try list[:] = [1, 2, 3] (by the way list is wrong name for a variable. Thinking about [0, 1] = [1, 2, 3] is a complete nonsense. Anyway, what do you think means the object itself is passed? What is copied to the function in your opinion?
  • BugShotGG
    BugShotGG over 11 years
    Actually this is confirmed its pass by reference value. +1 for this answer although the example wasnt good.
  • Mike Graham
    Mike Graham over 11 years
    No, it's exactly like Java's semantics for objects. I'm not sure what you mean by "In the first case, the returned value will be a copy of the input, and identical in the second case." but that statement seems to be plainly incorrect.
  • stoic_monk
    stoic_monk over 11 years
    My comment is indeed incorrect, but I stand on the fact that python semantics are different from java, as explained in the referred article. In python, whether changes within a function are visible outside it for its argument depends on the mutability, not on being a special type (say object vs primitive types in java), and the argument passing 'protocol' is the same for everything in python.
  • cayhorstmann
    cayhorstmann over 11 years
    It is exactly the same as in Java. Object references are passed by value. Anyone who thinks differently should attach the Python code for a swap function that can swap two references, like this: a = [42] ; b = 'Hello'; swap(a, b) # Now a is 'Hello', b is [42]
  • cayhorstmann
    cayhorstmann over 11 years
    It is simply not true that all languages are call by value. In C++ or Pascal (and surely many others that I don't know), you have call by reference. For example, in C++, void swap(int& x, int& y) { int temp = x; x = y; y = temp; } will swap the variables passed to it. In Pascal, you use var instead of &.
  • cayhorstmann
    cayhorstmann over 11 years
    Inventing new terminology (such as "pass by reference value" or "call by object" is not helpful). "Call by (value|reference|name)" are standard terms. "reference" is a standard term. Passing references by value accurately describes the behavior of Python, Java, and a host of other languages, using standard terminology.
  • pepr
    pepr over 11 years
    @cayhorstmann: The problem is that Python variable has not the same terminology meaning as in other languages. This way, call by reference does not fit well here. Also, how do you exactly define the term reference? Informally, the Python way could be easily described as passing the address of the object. But it does not fit with a potentially distributed implementation of Python.
  • stoic_monk
    stoic_monk over 11 years
    Whether something is an object or not is irrelevant (especially since almost everything is an object in python, e.g. int, float, etc...). The mutability matters. You can write a swap function that would work for lists (mutable), but not for tuples or strings (immutable). See also this: python-course.eu/passing_arguments.php, which clearly shows a different behavior than java in some cases.
  • Lennart Regebro
    Lennart Regebro about 11 years
    Oh, that's sad. "It's passed by value, but the value is a reference". Sigh. Well, everything is a value. When the value is a reference, that's pass by reference. The difference in Python is minimal as Pythons variables aren't like C's variables, but calling it pass by value is definitely incorrect.
  • tom
    tom almost 11 years
    I down voted because the code(where you do assignment in function body) given for string and list is basically the same and has the same behavior. And list is mutable a string is not. Your answer did not cleared a thing for me. It just made me realize that I totally don't understand Python.
  • Claudiu
    Claudiu almost 11 years
    It is exactly the same as Java when you pass objects in Java. However, Java also have primitives, which are passed by copying the value of the primitive. Thus they differ in that case.
  • Richard Fung
    Richard Fung over 10 years
    @Lennart Regebro, just because the value is a reference to something doesn't make it pass by reference. In C++ you can actually pass by reference, and when you do, if you reassign the reference, the parameter you passed will actually be modified. In Python, if you try to reassign the parameter you will just be changing the mapping of the name in the namespace of your function, something which is fundamentally different. Still, the whole idea of pass by reference is so screwed up now because everyone is using it to describe a different thing.
  • Lennart Regebro
    Lennart Regebro over 10 years
    @Synderesis: "In C++"... - Well, yeah, but now we are talking about Python. Python is passing references. Since it is passing reference, that's reasonably "pass by reference". "In Python, if you try to reassign the parameter" - Yes, but that's a completely different issue. This is because Python doesn't have variables that point to a memory location like C/C++. It has objects, and variables are names for these objects.
  • Lennart Regebro
    Lennart Regebro over 10 years
    (Hence my upvote for David's post calling it "call-by-object".)
  • Richard Fung
    Richard Fung over 10 years
    @Lennart Regebro: I realize that, but in the end you could also consider Python to be pass by value with the values being references. Of course, that is why I added that last line anyway. Defining terms to mean different things for different languages is by all means useless, because the whole point of defining those terms is to make it clear what you are saying.
  • Lennart Regebro
    Lennart Regebro over 10 years
    This answer is hence factually incorrect, and have been upvotes as "thanks" by newbies who don't understand the internals of Python. Which is why it makes me sad.
  • Richard Fung
    Richard Fung over 10 years
    @Lennart Regebro "it is a reference passed as a value the type is a reference/pointer and you would have to dereference it to access it." I don't see how that is true. Java uses references but is pass by value, and behaves identically to Python in that it has objects and variables are names referencing these objects. The statement you made earlier "When the value is a reference, that's pass by reference." is incorrect, because if it's pass by value, you can reassign the reference. However, in pass by reference, if you try to reassign the variable you are actually modifying it.
  • Lennart Regebro
    Lennart Regebro over 10 years
    @Synderesis: Once again, then: effbot.org/zone/call-by-object.htm See Davids answer. With your definition of pass-by-value, then EVERYTHING IS PASS BY VALUE. There exists no pass-by-reference with that wording of it, since pass-by-reference is when the value you pass is a reference, but you don't have to treat the value as a reference inside the function. What Java calls "pass-by-value, and the value is a reference" is exactly what pass-by-reference is. The whole point is that what Python and Java does does not exactly fit either concept as used in other languages.
  • Richard Fung
    Richard Fung over 10 years
    @Lennart Regebro "There exists no pass-by-reference with that wording of it, since pass-by-reference is when the value you pass is a reference" In C++ you can have true pass by reference. Java is pass by value: stackoverflow.com/questions/40480/is-java-pass-by-reference
  • Lennart Regebro
    Lennart Regebro over 10 years
    @Synderesis: I wish the "move this to chat" option was always available, coomments are really not the place for me to repeat the same thing over and over.
  • Honest Abe
    Honest Abe over 10 years
    I like this answer, but you might consider if the example is really helping or hurting the flow. Also, if you replaced 'reference value' with 'object reference' you would be using terminology that we could consider 'official', as seen here: Defining Functions
  • Honest Abe
    Honest Abe over 10 years
    I really appreciate learning about this from a developer. Is it true that the id() function returns the pointer's (object reference's) value, as pepr's answer suggests?
  • Raymond Hettinger
    Raymond Hettinger over 10 years
    @HonestAbe Yes, in CPython the id() returns the address. But in other pythons such as PyPy and Jython, the id() is just a unique object identifier.
  • pepr
    pepr over 10 years
    Well, but the official says... "arguments are passed using call by value (where the value is always an object reference, not the value of the object)." This way, you may be tempted to substitute it textually as ... arguments are passed using call by reference, which is a bit confusing beacuse it is not true. The confusion is caused by a bit more complex situation where none of the classical terms fits perfectly. I did not find any simpler example that would illustrate the behaviour.
  • Honest Abe
    Honest Abe over 10 years
    There is a footnote indicated at the end of that quote, which reads: "Actually, call by object reference would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it..." I agree with you that confusion is caused by trying to fit terminology established with other languages. Semantics aside, the things that need to be understood are: dictionaries / namespaces, name binding operations and the relationship of name→pointer→object (as you already know).
  • Honest Abe
    Honest Abe over 10 years
    "...parameter passed in..." is incorrect use of terminology. A parameter is a named entity in a function (or method) definition that specifies an argument (or in some cases, arguments) that the function can accept. An argument is a value passed to a function (or method) when calling the function.
  • Veky
    Veky about 10 years
    @pepr objects aren't literals. They are objects. The only way to talk about them is giving them some names. That's why it's so simple once you grasp it, but enormously complicated to explain. :-)
  • pepr
    pepr about 10 years
    @Veky: I am aware of that. Anyway, the list literal is converted to the list object. Actually, any object in Python can exist without a name, and it can be used even when not given any name. And you can think about them as about anonymous objects. Think about objects being the elements of a lists. They need not a name. You can access them through indexing of or iterating through the list. Anyway, I insist on [0, 1] = [1, 2, 3] is simply a bad example. There is nothing like that in Python.
  • Veky
    Veky about 10 years
    @pepr: I don't necessarily mean Python-definition names, just ordinary names. Of course alist[2] counts as a name of a third element of alist. But I think I misunderstood what your problem was. :-)
  • Veky
    Veky about 10 years
    Argh. My English is obviously much worse than my Python. :-) I'll try just once more. I just said you have to give object some names just to talk about them. By that "names" I didn't mean "names as defined by Python". I know Python mechanisms, don't worry.
  • yantrab
    yantrab almost 10 years
    "Python has no variables" is a silly and confusing slogan, and I really wish people would stop saying it... :( The rest of this answer is good!
  • Lutz Prechelt
    Lutz Prechelt almost 10 years
    It may be shocking, but it is not silly. And I don't think it is confusing either: It hopefully opens up the recipient's mind for the explanation that is coming and puts her in a useful "I wonder what they have instead of variables" attitude. (Yes, your mileage may vary.)
  • yantrab
    yantrab almost 10 years
    would you also say that Javascript has no variables? They work the same as Python's. Also, Java, Ruby, PHP, .... I think a better teaching technique is, "Python's variables work differently than C's."
  • laycat
    laycat almost 10 years
    yea, however if you do x = [ 2, 4, 4, 5, 5], y = x, X[0] = 1 , print x # [1, 4 ,4, 5, 5] print y # [1, 4, 4, 5, 5]
  • Max P Magee
    Max P Magee almost 10 years
    I was tempted to post a similar response- the original questioner may not have known that what he wanted was in fact to use a global variable, shared among functions. Here's the link I would have shared: stackoverflow.com/questions/423379/… In answer to @Tim, Stack Overflow is not only a question and answer site, it's a vast repository of reference knowledge that only gets stronger and more nuanced- much like an active wiki- with more input.
  • brain storm
    brain storm almost 10 years
    @Claudiu: Its not only in the case of Java primitives, any immutable object in Java will behave same as primitives such as String which is a Java object
  • M Katz
    M Katz over 9 years
    +1 for small amount of text giving the essential workaround to the problem of Python not having pass-by-reference. (As a follow-on comment/question that fits here as well as anywhere on this page: It's not clear to my why python can't provide a "ref" keyword like C# does, that simply wraps the caller's argument in a list like this, and treat references to the argument within the function as the 0th element of the list.)
  • yantrab
    yantrab over 9 years
    Yes, Java has variables. So does Python, and JavaScript, Ruby, PHP, etc. You wouldn't say in Java that int declares a variable, but Integer does not. They both declare variables. The Integer variable is an object, the int variable is a primitive. As an example, you demonstrated how your variables work by showing a = 1; b = a; a++ # doesn't modify b. That's exactly true in Python also (using += 1 since there is no ++ in Python)!
  • Justas
    Justas over 9 years
    Nice. To pass by ref, wrap in [ ]'s.
  • Lutz Prechelt
    Lutz Prechelt over 8 years
    The concept of "variable" is complex and often vague: A variable is a container for a value, identified by a name. In Python, the values are objects, the containers are objects (see the problem?) and the names are actually separate things. I believe it is much tougher to get an accurate understanding of variables in this manner. The names-and-objects explanation appears more difficult, but is actually simpler.
  • KobeJohn
    KobeJohn over 8 years
    I thought I had replied to this long ago but I don't see it. For completeness - cayhorstmann misunderstood my answer. I was not saying everything is call by value in the terms that most people first learn regarding C / C++. It was simply that some value is passed (value, name, pointer, etc.) and that the terms used in Blair's original answer were inaccurate.
  • Tim Richardson
    Tim Richardson over 8 years
    using the id() function helps clarify matters, because it makes it clear when Python creates a new object (so I think, anyway).
  • user22866
    user22866 over 8 years
    lovely, makes it easy to spot the subtle diff that there is an intermediate assignment, not obvious to a casual onlooker. +1
  • Martijn Pieters
    Martijn Pieters almost 8 years
    It doesn't matter if A is mutable or not. If you assign something different to B, A doesn't change. If an object is mutable, you can mutate it, sure. But that has nothing to do with assignment directly to a name..
  • Zenadix
    Zenadix almost 8 years
    @Martijn You're right. I removed the part of the answer that mentions mutability. I don't think it can get any simpler now.
  • Martijn Pieters
    Martijn Pieters almost 8 years
    Thanks for the update, much better! What confuses most people is assignment to a subscription; e.g. B[0] = 2, vs. direct assignment, B = 2.
  • Sherlock70
    Sherlock70 almost 8 years
    I really don't see how this answer could be helpful in light of the question. No solution is given, only the status quo of python is recited. How can you pass an argument, so that it can be changed? Most of the answers here don't give a solution. But this one, denies the existence of the obvious in the first lines, so it stands out of the pack. Sorry for the downvote, but it just made me a bit mad.
  • Hatshepsut
    Hatshepsut almost 8 years
    "A is assigned to B." Is that not ambiguous? I think in ordinary English that can mean either A=B or B=A.
  • Madivad
    Madivad almost 8 years
    I do like the visual representation, but still misses the point of mutable vs immutable which makes the right leg moot since there will be no append available. (still got an upvote for the visual rep though) :)
  • Elazar
    Elazar over 7 years
    Unless you look at locals() etc., this is exactly like Java. In Java the address-space of references is an implementation detail, but in Python is a string in some scope (__dict__). In C it would be numbers in a global scope. Also, there is only one type of primitive in Python (reference to object) and several primitives in Java, one of which is reference to Object. Pass-by-reference in Python would mean "pass the scope and the name of the variable" but currently there is no such thing. it can be done explicitly - and it is, when emulating this mechanism using a class (which is a scope).
  • Elazar
    Elazar over 7 years
    @Claudiu you are 100% right, except Java does not differ with the behavior of the additional primitives - it merely does have additional primitives, where Python don't. Other differences are visible when you look at locals() and some other meta-stuff - the scopes are implemented in a different way, and this implementation detail is visible in Python.
  • Tommy
    Tommy over 7 years
    I've most often seen the term "call-by-object-reference" not "by assignment"
  • Bill
    Bill over 7 years
    As a means to pass a reference to a name, why not pass the name itself as a string? Then use eval(name) to get the current object that the name references.
  • Luke Davis
    Luke Davis over 7 years
    Woah... so it makes sense that lists are mutable because one can imagine saying "ok python, make these boxes for me"... then the contents of the boxes can be modified. But things like strings and numbers can without complication point to a series of 1s and 0s in your memory, so it makes more sense to "tag" them with names.
  • akki
    akki about 7 years
    This answer and this blog post by effbot on python-objects together make things as clear as they can be.
  • akki
    akki about 7 years
  • Erich
    Erich over 6 years
    var·i·a·ble ˈverēəb(ə)l/Submit adjective 1. not consistent or having a fixed pattern; liable to change. I would argue that python does have "Variables"
  • rkachach
    rkachach over 6 years
    "but if you rebind the reference in the method, the outer scope will know nothing about it", well the if the passed reference is mutable and you performed some operations (let say appended some values to the list) then these operations will be visible by the outer scope. The outer-scope will stop seeing changes only once the rebind is performed. All the previous operations do affect the original object.
  • rkachach
    rkachach over 6 years
    "That is all there is to it. Mutability is irrelevant for this question." yes it does. If the self.variable were mutable then it could be changed inside the function self.change(). Thus, passing an immutable type as parameter function will never affect the passed "variable".
  • Christian Groleau
    Christian Groleau over 6 years
    I like this answer. To further the idea of "variables" vs "names" (emphasis on the quotes) may be found here: Code Like a Pythonista: Idiomatic Python
  • Christian Groleau
    Christian Groleau over 6 years
    At first glance this answer seems to sidestep the original question. After a second read I've come to realize that this makes the matter quite clear. A good follow up to this "name assignment" concept may be found here: Code Like a Pythonista: Idiomatic Python
  • Tony Suffolk 66
    Tony Suffolk 66 about 6 years
    Function calls do not create new references - use the id function inside and outside of the function to confirm that. The difference is what happens to the object when you attempt to change it inside the function.
  • Mark Ransom
    Mark Ransom about 6 years
    @TonySuffolk66 id gives the identity of the object referenced, not the reference itself.
  • Tony Suffolk 66
    Tony Suffolk 66 about 6 years
    Mark - I took your use of reference to mean a object; when a function is called a new binding is created of an existing object to a new name (with a increase in the Ref count). Most documentation I have seen talks about this as a new binding, and not a new reference. Apologies for misunderstanding.
  • Mark Ransom
    Mark Ransom about 6 years
    @TonySuffolk66 I come from a C++ background, so I might be a little loose on the terminology. A C++ reference is the closest thing to a Python variable.
  • Tony Suffolk 66
    Tony Suffolk 66 about 6 years
    @MarkRansom - strictly speaking Python doesn't have 'variables' - well not in a C/C++ way of having a memory location which is known by that name. What Python has is one or more names which are bound to a reference to object - or sometime a name is bound to a container of object references. Oh the joys of terminology :-)
  • Bishwas Mishra
    Bishwas Mishra about 6 years
    Although this works. It is not pass by reference. It is 'pass by object reference'.
  • Happy Ahmad
    Happy Ahmad almost 6 years
    @EthanFurman You are wrong. Even if you read the link in DavidCournapeau's answer that is Call By Object, you will see that all of the expressions “call by object”, “call by sharing“ or “call by object reference“, have the same meaning that is using an address to access the object. And for sure the address has to be determined from namespace. I can't accept that "Call by object reference" is different from "Call by reference".
  • GeorgeOfTheRF
    GeorgeOfTheRF almost 6 years
    @BlairConrad "The parameter passed in is actually a reference to an object (but the reference is passed by value)". This sounds similar to pass by reference. How is pass by reference and assignment different? Can you give an example to explain "pass by assignment"?
  • Marc Stober
    Marc Stober almost 6 years
    @ML_Pro, "pass by assignment" seems to be a term made up by the Python documenters to describe "pass by value". For the user, I see no functional difference between passing a value that is a reference (or handle) as happens in languages such as Java or C# and what Python does, and I'd never use the term "pass by assignment"; it was edited into the answer, I assume to align with the documentation.
  • Yasir Jan
    Yasir Jan over 5 years
    So, can we say that a mutable object is passed by reference and an immutable object is not ?
  • Mark Ransom
    Mark Ransom over 5 years
    @YasirJan no, they're both passed by reference. It's just that for an immutable object the reference doesn't help you.
  • Yasir Jan
    Yasir Jan over 5 years
    @MarkRansom Thanks. The 'call by assignment' way of describing it from python docs made more sense to me and I now I understand it.
  • Minh Tran
    Minh Tran over 5 years
    p is reference to a mutable list object which in turn stores the object obj. The reference 'p', gets passed into changeRef. Inside changeRef, a new reference is created (the new reference is called ref) that points to the same list object that p points to. But because lists are mutable, changes to the list are visible by both references. In this case, you used the ref reference to change the object at index 0 so that it subsequently stores the PassByReference('Michael') object. The change to the list object was done using ref but this change is visible to p.
  • Minh Tran
    Minh Tran over 5 years
    So now, the references p and ref point to a list object that stores the single object, PassByReference('Michael'). So it follows that p[0].name returns Michael. Of course, ref has now gone out of scope and may be garbage collected but all the same.
  • Minh Tran
    Minh Tran over 5 years
    You have not changed the private instance variable, name, of the original PassByReference object associated with the reference obj, though. In fact, obj.name will return Peter. The aforementioned comments assumes the definition Mark Ransom gave.
  • Minh Tran
    Minh Tran over 5 years
    Point being, I don't agree that it's a hack (which I take to mean to refer to something that works but for reasons unknown, untested, or unintended by the implementer). You simply replaced one PassByReference object with another PassByReference object in your list and referred to the latter of the two objects.
  • Minh Tran
    Minh Tran over 5 years
    @MarkRansom What exactly is a reference? Your definition doesn't go beyond suggesting that it is "something" that points/refers to an object (which is a helpful definition to aid in describing what a reference does but not necessarily what it is).
  • Mark Ransom
    Mark Ransom over 5 years
    @MinhTran in the simplest terms, a reference is something that "refers" to an object. The physical representation of that is most likely a pointer, but that's simply an implementation detail. It really is an abstract notion at heart.
  • John
    John over 4 years
    Old but I feel obliged to correct it. Strings are passed by reference in both Java and C#, NOT by value
  • NoName
    NoName over 4 years
    Okay, so when you pass a list reference variable into the method, you're actually giving it a "copy" of the list reference. That's why changing what the "list reference copy" is pointing to doesn't change what the "original list reference" is pointing to.
  • Abhinav
    Abhinav over 4 years
    What do you mean by B is modified in-place?B is not an object
  • kasimir
    kasimir about 4 years
    Yes, this solves the 'pass by reference' in my use case as well. I have a function that basically cleans up values in a dict and then returns the dict. However, while cleaning up it may become apparent a rebuild of a part of the system is required. Therefore, the function must not only return the cleaned dict but also be able to signal the rebuild. I tried to pass a bool by reference, but ofc that doesn't work. Figuring out how to solve this, I found your solution (basically returning a tuple) to work best while also not being a hack/workaround at all (IMHO).
  • juanpa.arrivillaga
    juanpa.arrivillaga almost 4 years
    "But then I found something neat in Python that I don't think I have seen in other languages before, namely that you can return more than one value from a function" No, you can't. What you are doing is returning a single value, a tuple, which is what the expression a, b, c creates. You then use iterable unpacking to unpack that tuple into separate variables. Of course, in effect, you can think of this as "returning multiple values", but you aren't actually doing that, you are returning a container.
  • Magnus
    Magnus almost 4 years
    @juanpa.arrivillaga, yes, I was aware of that when I wrote my answer, I had just read about it. But I just described the whole thing in a practical way without going into the details of how it works and add unnecessary length to my answer. You can indeed return multiple values from a function, if it is done in an object or similar, like in a tuple (which in Python is taken care of in the neat way I showed). When I order things from a company, they can send me multiple things, even if it is all in one package.
  • Myridium
    Myridium over 3 years
    This answer is at best misleading, and at worst outright false.
  • Myridium
    Myridium over 3 years
    @pepr - it may technically correct (I cannot understand 50% of it) but it offers no clarification to a beginner who is trying to fit the behaviour of python into a conceptual model where something is either passed by reference or passed by value. This is a pragmatic question, let alone a theoretical one. The answer is that Python 'passes by assignment', behaving differently for mutable and immutable types. I was surprised to learn that id(x) is the same as what was passed in, because assigning a new value to the parameter has a different result than assigning a value to the x before input.
  • Myridium
    Myridium over 3 years
    The example given leads the reader to believe Python behaves one way, and yet if you give the example of an integer (immutable type) it will appear to behave the other way! How is the mutable type behaviour reconciled with your assertion that everything is passed by reference, and with the fact that id is preserved? This needs to be explained.
  • pepr
    pepr over 3 years
    @Myridium: Python does not use the pass by value (as compiled languages do). It always passes the address (the id) of the target object. Of course, if the object is mutable, its content can be changed by assigning it the new value. If the object is immutable, then the assignment creates new object and the other one is untouched. However, it is not caused by how the object was passed into the procedure. It is the feature related to mutable/immutable in general.
  • Myridium
    Myridium over 3 years
    @pepr - okay, thanks, I think I understand. I suppose the difference in behaviour between assigning the variable inside or outside a function is that inside a function, the 'labels' for the variables have a restricted scope.
  • pepr
    pepr over 3 years
    @Myridium: Well, not exactly. After passing the argument, both outer and inner variable point to the same target object.
  • juanpa.arrivillaga
    juanpa.arrivillaga about 3 years
    @HappyAhmad it absolutely is different to call by reference. If Python supported call by reference, you could do something like def foo(&var): var = 2 then x = 0; y = 1; foo(x); foo(y) then print(x, y) would print 2 2
  • juanpa.arrivillaga
    juanpa.arrivillaga about 3 years
    @BlairConrad because that is simply confusing the implementation for the semantics. It isn't pass by value because the value isn't copied. The value is the object, python doesn't support reference types like pointers. The fact that CPython uses pointers is irrelevant, I could write a Python interpreter in Fortran using only call by reference internally, and that wouldn't make Python call by reference. Yes, "pass by assignment" is a Pythonism, but academically, it is known as call by sharing
  • juanpa.arrivillaga
    juanpa.arrivillaga about 3 years
    @NoName no. That isn't how it works at all. Assignment doesn't work like in C/C++. An assignment statement merely changes what a name refers to in a namespace. Often, it is literally just chaning the value of a key in a dict (global namespaces and module namespaces are implemented as python dict objects)
  • Naren
    Naren about 3 years
    This is by far the most helpful answer (IMHO obviously) - but it does take time to distill what is being said here - that too if you are coming from ~C like language.
  • Mark Ransom
    Mark Ransom about 3 years
    @Abhinav in Python, EVERYTHING is an object - even simple integers. But some objects can be modified (mutable) and some can't. If the object has an append method then it must be mutable.
  • Mark Ransom
    Mark Ransom about 3 years
    This is a great answer that illustrates a key core concept of Python, but I think somewhere along the way you lost the connection to the original question.
  • Charlie Parker
    Charlie Parker about 3 years
    apologies for the question, especially since the discussion seems to complain about using new terminology, but it's unclear to me. What does pass by reference values mean? Perhaps defining it in your answer would be useful :) Is a reference a pointer like thing?
  • pepr
    pepr about 3 years
    @CharlieParker: I the third paragraph: "You can think about a reference value as the address of the target object." Anyway, this holds only for C-Python. Technically the function id() can return a different kind of unique identifier -- then that would be the reference value. Yes, I consider reference as equal to pointer that is never null. But pointers in compiled languages store the address. In Python, the reference/pointer is hidden and can possibly generalized for other kind of id's.
  • ElmoVanKielmo
    ElmoVanKielmo almost 3 years
    Hey, is this a joke?
  • pippo1980
    pippo1980 almost 3 years
    X[0] or x[0] ? don't get it
  • Muhammad Zubair
    Muhammad Zubair over 2 years
    Confusing language used on lists passed into the two functions. In both cases, the list is passed by reference, however, in the first case, the list is modified so changes are visible outside the function. On the other hand, in the second case, a new list is assigned to the passed parameter, so it makes a new list without making changes to the list passed to the function. That's why changes are not visible outside the function
  • marc_r
    marc_r over 2 years
    One should perhaps note that in the second example (mutable object), you cannot update the reference either: var = ['Changed'] won't have the desired effect. WIth var[0] = 'Changed', the object identity is the same; we just use the object's interface to make changes to it. It would be interesting to have a notation like var[] = ... that updates the actual reference (replaces the object as a whole).
  • Mark Ransom
    Mark Ransom over 2 years
    @marc_r I thought that was obvious from the way I explained the mechanics. Mutating a list isn't a real answer to the question, it's just a workaround - the closest thing that Python allows.
  • jjaskulowski
    jjaskulowski over 2 years
    No. Everything is passed by value in c#. It is that the value of variable that is an object in c# is exactly and heap ID/address of the object. So when you set something in a function to a new object you set the variable in function to address. Passing by reference means passing an adres to value which is an address to the value for struct types but address to pointer in case of objects.
  • juanpa.arrivillaga
    juanpa.arrivillaga over 2 years
    "For basic types, python and c++ also behave the same to each other, in that copies of the instances are now made", no that is not correct. Copies of objects are never made as part of the evaluation strategy
  • juanpa.arrivillaga
    juanpa.arrivillaga over 2 years
    @MuhammadZubair no, in neither case is pass by reference occurring. These terms have well understood meanings in programming languages, and Python never supports call by reference. If it were pass by reference, and a new list were assigned to the parameter, that change would be visible in the caller. That is a key feature of pass-by-reference. You've essentially proven your own point incorrect.\
  • moe fear
    moe fear over 2 years
    Your comment makes no sense. Are you speaking of python or c++? If python, then how the interpreter goes about differs whether they are basic types or not. Internally python uses an equivalent of a stack to manage local basic object types, and these are copies. If they weren't, then the originals outside the function call would be irreversibly modified, which they arent, which raises the question, have you ever even used python?!
  • juanpa.arrivillaga
    juanpa.arrivillaga over 2 years
    I'm speaking of Python. The interpreter makes no distinction between "basic types" and "other types" And in CPython at least, all objects are allocated on a privately managed heap. You seem to have no basic knowledge about the internals of Python, let alone the semantics of the langauge
  • juanpa.arrivillaga
    juanpa.arrivillaga over 2 years
    The objects aren't modified by assignment to the parameter, but that works that way for all objects, because it isn't an issue of the type of object, but rather, the semantics of assignment and the evaluation strategy. In Python, some types are merely immutable. that is, they expose no mutator methods. However, we can (if we are willing to delve into implementation details) mutate them, and indeed, you'll see the evaluation strategy is exactly the same
  • moe fear
    moe fear over 2 years
    This isn't about objects! It's about BASIC TYPES. Python treats them behind the scenes as objects, and they have to exist somewhere in memory. But when passed as parameters to a function, COPIES have to be made (by fundamental rules of information theory), otherwise when the function returns, the original variables that were passed to the function, would also get modified. BUT THEY DON'T. TRY IT (Excuse the caps, I don't know how to achieve the bold effect). They only way this can be the case, is if there is a COPY somewhere else in memory, which is point of what is above.
  • moe fear
    moe fear over 2 years
    In other words... one way or another, irrespective how you consider it from a philosophical standpoint, python DOES treat basic types DIFFERENTLY than it does for "other types", just like C++. Saying "by assignment to the parameter" is pointless and philosophical, since if you change a basic type that is a member of "another type", using THAT SAME ASSIGNMENT OPERATOR, then UNLIKE "other types", the actual value DOES change, irrespective from where it is referenced after that.
  • moe fear
    moe fear over 2 years
    To clarify (since the last statement above is not fully correct but I can't edit it anymore: If you assign to an "other type", you are changing what instance it points to, without necessarily deleting the original instance (as long as it is pointed to by another reference). When you do this to a basic type though, even though it's technically an object in python, python still changes its actual value in memory, rather than what instance (or address) that reference points to. Python doesn't create a new instance (or memory location) just because you changed the value of an int, and then garbage
  • moe fear
    moe fear over 2 years
    collect the old one, although it would do this for "other types". And this difference holds despite using the same assignment operator in all cases.
  • juanpa.arrivillaga
    juanpa.arrivillaga over 2 years
    you are simply mistaken. What you are calling "basic types" are not treated in any way differently when they are passed to functions or by the assignment operator. You are operating under totally false premises.
  • juanpa.arrivillaga
    juanpa.arrivillaga over 2 years
    i.e. "If you assign to an "other type", you are changing what instance it points to, without necessarily deleting the original instance (as long as it is pointed to by another reference). When you do this to a basic type though, even though it's technically an object in python, python still changes its actual value in memory, rather than what instance (or address) that reference points to. " is totally incorrect, assuming what you are saying is even coherent (it isn't, one doesn't assign to types, you assign to variables).
  • moe fear
    moe fear over 2 years
    it is correct, you have no idea what information is, and how it occupies space in computer memory. My advice, pick up a good "For Dummies.." book on information theory and compilers/interpreters. It's not my fault you are unable to comprehend complex explanations (or even the simple one above, which you could have tried, but obviously haven't).
  • gast128
    gast128 over 2 years
    Good explanation. The confusing part for me (as C++) developer is that a function can change the contents ('pass by reference') but it depends on the argument passed in.
  • Mohamed Fathallah
    Mohamed Fathallah over 2 years
    i Know you are expert when you said address copy (that why ref exist) which pass the reference it self not the copy in C#
  • Mark Ransom
    Mark Ransom over 2 years
    @kasimir this is one of the things I really love about Python. Because it's so easy to return multiple values as a tuple, it's very rare to even need to pass by reference.
  • kasimir
    kasimir over 2 years
    @MarkRansom me too! I did a lot of PHP programming and passing by reference is quite common there, but can be a pain when trying to debug. Python lets you avoid this, so yet another reason for me to love Python more :-)
  • iperov
    iperov about 2 years
    "Assignment binds a name to an object." - this is why properties must be deleted from python, because 'obj.some_prop = val' does some hidden non-obvious logic instead of binding object to name.
  • timgeb
    timgeb about 2 years
    "Something else is assigned to B" should be "B is assigned to something else". Names are assigned to values, not the other way around. Names refer to values, values don't know what names they have.
  • Lutz Prechelt
    Lutz Prechelt about 2 years
    @iperov Why? some_prop is a perfectly fine name like any other. No problem and nothing non-obvious there at all. (Except maybe that there is more than a single namespace in Python and the question and answer do not talk about that aspect.)
  • iperov
    iperov about 2 years
    @Lutz Prechelt it is not clear to those who have not designed complex architectures. Any non-obvious thing to the "external user of a class" is a pitfall, or a shot in the leg.