Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can this be called Pass By Reference?

According to this tutorial, Python uses "Pass By Reference."

They then go on to give the following example. On what planet is this "Pass By Reference"? It looks like a clear cut case of "Pass By Value" to me.

Thoughts?

def changeme( mylist ):
   mylist = [1,2,3,4];
   print "Values inside the function: ", mylist
   return

mylist = [10,20,30];
changeme( mylist );
print "Values outside the function: ", mylist

The parameter mylist is local to the function changeme. Changing mylist within the function does not affect mylist. The function accomplishes nothing and finally this would produce the following result:

# Values inside the function:  [1, 2, 3, 4]
# Values outside the function:  [10, 20, 30]

Update, Conclusion:

  1. per answer by viraptor below, "according to the docs, python is pass-by-value". So the tutorial is clearly wrong.

  2. Python is not "call by reference", it is "call by sharing". This means a reference can be passed to a local subroutine, updated by the subroutine, and the update stays local to the subroutine and doesn't automatically affect the global value of the reference.

like image 564
thanks_in_advance Avatar asked Apr 25 '16 23:04

thanks_in_advance


People also ask

How do you call by reference?

The call by reference method of passing arguments to a function copies the address of an argument into the formal parameter. Inside the function, the address is used to access the actual argument used in the call. It means the changes made to the parameter affect the passed argument.

Why do we pass by reference?

If you recall, using pass by reference allows us to effectively “pass” the reference of a variable in the calling function to whatever is in the function being called. The called function gets the ability to modify the value of the argument by passing in its reference.

Which language is pass by reference?

Pass by reference in C programming language is the addresses which are sent as arguments.

How do you pass something by reference in C++?

To pass the value by reference, argument reference is passed to the functions just like any other value. So accordingly you need to declare the function parameters as reference types as in the following function swap(), which exchanges the values of the two integer variables pointed to by its arguments.


3 Answers

It is neither. It is call by sharing. I've also heard the term "pass by reference value" used.

Also known as "call by object" or "call by object-sharing," call by sharing is an evaluation strategy first named by Barbara Liskov et al. for the language CLU in 1974. It is used by languages such as Python, Iota, Java (for object references), Ruby, JavaScript, Scheme, OCaml, AppleScript, and many others. However, the term "call by sharing" is not in common use; the terminology is inconsistent across different sources. For example, in the Java community, they say that Java is call-by-value, whereas in the Ruby community, they say that Ruby is call-by-reference, even though the two languages exhibit the same semantics. Call by sharing implies that values in the language are based on objects rather than primitive types, i.e. that all values are "boxed".

The semantics of call by sharing differ from call by reference in that assignments to function arguments within the function aren't visible to the caller (unlike by reference semantics), so e.g. if a variable was passed, it is not possible to simulate an assignment on that variable in the caller's scope. However, since the function has access to the same object as the caller (no copy is made), mutations to those objects, if the objects are mutable, within the function are visible to the caller, which may appear to differ from call by value semantics. Mutations of a mutable object within the function are visible to the caller because the object is not copied or cloned — it is shared.

like image 179
Amadan Avatar answered Sep 18 '22 11:09

Amadan


It is pass-by-value, where all the values are pointers to objects. You might think this would imply that you can use the passed-in pointer to change the caller's variable, making it pass-by-reference, but you can't, so it's not.

Key to understanding how Python value-passing works is knowing that there are no "unboxed" (non-object) values. Integers are objects, and a variable that "contains" an integer is really a pointer to an integer object stored somewhere other than the variable. Floats, Booleans, ditto.

Variables don't really "hold" values in Python in the sense that they do in, say, C. And so assignment always consists of making the variable name point to a different object.

If an object passed into a function is mutable, the function can change it, but this must be done entirely without changing what object its name(s) point to. For example:

some_digits_of_pi = [3, 1, 4, 1, 5, 9, 2, 7]

def extend_pi(x):
    x[-1] = 6
    x += [5, 3, 5, 9]

Here we are mutating x inside the function. (For a list, += is essentially list.extend.) Since x is never changed to point to a different object, the changes are made to the list that was passed in. The name some_digits_of_pi refers to the same object as is being modified in the function, so the caller will see that their list of that name has been changed.

If we write x = [2, 7, 1, 8, 2, 8, 1, 8] at the end of the function, that would create a new list object and point the local name x at it. It doesn't change what the caller's variable points to, so that list is not changed by that statement.

In other words, you can't make the caller's variable (some_digits_of_pi in this case) point to a different object. If you change x to point to a different object inside the function, only x points to that object.

Numbers, strings, tuples, and the like work exactly the same way. A pointer to the object is passed in; if you change the value of the argument inside the function, it is made to point to a different object, and this naturally does not change the caller's variable. It only seems different because these types of objects aren't mutable, and there isn't any way to change them in place.

An additional point of confusion is that it looks like ints and lists both have += operators, but it happens that += on an int does something very different from what the same operation does on a list. On a list, += returns the same list object (modified), while on an integer, it may return a completely different object (since integers are immutable).

like image 38
kindall Avatar answered Sep 17 '22 11:09

kindall


The naming of the calls is different depending on who you talk to. One thing it's definitely not, is pass-by-reference though.

Both technically and according to the docs, python is pass-by-value.

[...] Otherwise, the value of the argument is placed in the slot, filling it (even if the expression is None, it fills the slot). When all arguments have been processed, the slots that are still unfilled are filled with the corresponding default value from the function definition. [...]

Now, just because the values are actually references, that causes people to argue about the convention and define new names to describe what's going on from a more practical point of view. Call by value reference, by sharing, by handle, etc. are all different names people could use.

like image 26
viraptor Avatar answered Sep 19 '22 11:09

viraptor