Python : When is a variable passed by reference and when by value?

46,636

Solution 1

Everything in Python is passed and assigned by value, in the same way that everything is passed and assigned by value in Java. Every value in Python is a reference (pointer) to an object. Objects cannot be values. Assignment always copies the value (which is a pointer); two such pointers can thus point to the same object. Objects are never copied unless you're doing something explicit to copy them.

For your case, every iteration of the loop assigns an element of the list into the variable loc. You then assign something else to the variable loc. All these values are pointers; you're assigning pointers; but you do not affect any objects in any way.

Solution 2

Effbot (aka Fredrik Lundh) has described Python's variable passing style as call-by-object: http://effbot.org/zone/call-by-object.htm

Objects are allocated on the heap and pointers to them can be passed around anywhere.

  • When you make an assignment such as x = 1000, a dictionary entry is created that maps the string "x" in the current namespace to a pointer to the integer object containing one thousand.
  • When you update "x" with x = 2000, a new integer object is created and the dictionary is updated to point at the new object. The old one thousand object is unchanged (and may or may not be alive depending on whether anything else refers to the object).
  • When you do a new assignment such as y = x, a new dictionary entry "y" is created that points to the same object as the entry for "x".
  • Objects like strings and integers are immutable. This simply means that there are no methods that can change the object after it has been created. For example, once the integer object one-thousand is created, it will never change. Math is done by creating new integer objects.
  • Objects like lists are mutable. This means that the contents of the object can be changed by anything pointing to the object. For example, x = []; y = x; x.append(10); print y will print [10]. The empty list was created. Both "x" and "y" point to the same list. The append method mutates (updates) the list object (like adding a record to a database) and the result is visible to both "x" and "y" (just as a database update would be visible to every connection to that database).

Hope that clarifies the issue for you.

Solution 3

It doesn't help in Python to think in terms of references or values. Neither is correct.

In Python, variables are just names. In your for loop, loc is just a name that points to the current element in the list. Doing loc = [] simply rebinds the name loc to a different list, leaving the original version alone.

But since in your example, each element is a list, you could actually mutate that element, and that would be reflected in the original list:

for loc in locs:
    loc[0] = loc[0] * 2

Solution 4

When you say

loc = []

you are rebinding the loc variable to a newly created empty list

Perhaps you want

loc[:] = []

Which assigns a slice (which happens to be the whole list) of loc to the empty list

Solution 5

Everything is passed by object. Rebinding and mutating are different operations.

locs = [ [1], [2] ]
for loc in locs:
    del loc[:]

print locs
Share:
46,636
Yugal Jindle
Author by

Yugal Jindle

Everybody is a genius. But if you judge a fish by its ability to climb a tree, it will live its whole life believing that it is stupid. -- Anonymous Github : YugalJindle Twitter : @YugalJindle Google+ : +YugalJindle LinkedIn : http://www.linkedin.com/in/YugalJindle

Updated on August 03, 2020

Comments

  • Yugal Jindle
    Yugal Jindle almost 4 years

    Possible Duplicate:
    Python: How do I pass a variable by reference?

    My code :

    locs = [ [1], [2] ]
    for loc in locs:
        loc = []
    
    print locs
    # prints => [ [1], [2] ]
    

    Why is loc not reference of elements of locs ?

    Python : Everything is passed as reference unless explicitly copied [ Is this not True ? ]

    Please explain.. how does python decides referencing and copying ?

    Update :

    How to do ?

    def compute(ob):
       if isinstance(ob,list): return process_list(ob)
       if isinstance(ob,dict): return process_dict(ob)
    
    for loc in locs:
       loc = compute(loc)  # What to change here to make loc a reference of actual locs iteration ?
    
    • locs must contain the final processed response !
    • I don't want to use enumerate, is it possible without it ?
  • Li-aung Yip
    Li-aung Yip about 12 years
    It might be helpful to read Idiomatic Python - "other languages have variables, Python has labels." The rest of it is good reading too. ;)
  • Yugal Jindle
    Yugal Jindle about 12 years
    How to modify each element of the container ? \
  • Daniel Roseman
    Daniel Roseman about 12 years
    @Yugal which part of what I've written above was not clear?
  • Yugal Jindle
    Yugal Jindle about 12 years
    Generally, I just want to process each element of my container. So, how can that be acheived ? If everything is a label that seems to be a disadvantage when actaully want to edit the element.
  • Joel Cornett
    Joel Cornett about 12 years
    @YugalJindle : To modify elements in a list, use the square brackets to reference items in that list.
  • Yugal Jindle
    Yugal Jindle about 12 years
    That is a specific solution for list, the loop may not always be aware of the object type. A method may be processing the loc which does different stuff for dict and list.
  • Yugal Jindle
    Yugal Jindle about 12 years
    In my point of view - You described it the best. Just tell me the answer of the Update to the question - that part you missed.
  • Anton Belov
    Anton Belov almost 11 years
    I believe this last example is what OP was looking for !
  • Andrew S
    Andrew S about 7 years
    So what happens with integer and float numbers then? Are they just considered immutable objects? How does python manage that as I'm sure it cannot hold all conceivable numbers in memory ready to be referenced.
  • newacct
    newacct about 7 years
    @AndrewS: Integers and floats are indeed immutable (it should be apparent that they do not have methods that mutate themselves). I am not sure what the second part of your comment means.
  • Andrew S
    Andrew S about 7 years
    What I'm saying by that second point is lets sat that I have two lines X = 150 and y = 150 on another. Will there be two separate copies of 150 in memory or one immutable object pooled in the same way Java Pools it's immutable Strings.
  • newacct
    newacct about 7 years
    @AndrewS: Maybe they are the same and maybe they aren't. Why does it matter? This has nothing to do with mutability or semantics of assignment.
  • Andrew S
    Andrew S about 7 years
    It matters when you want to understand the implementation techniques in use.
  • juanpa.arrivillaga
    juanpa.arrivillaga almost 4 years
    @AndrewS yes, float and int objects are... objects. And they are immutable. Everything in Python is an object. The behavior of the example you gave is implementation dependant, and could change given any python version, even in minor-version updates. But basically, the CPython compiler will often optimize immutable constant expressions to the same object. How and when it happens depends on a lot of things, and again, is an implementation detail