Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Thursday, July 28, 2016

How can this be called Pass By Reference?

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]  

Answer by Serdalis for How can this be called Pass By Reference?


As per @Amadan's answer Python uses Call by Sharing.

Within the function you have re-assigned the reference to a new list so it is no longer pointing to the list you passed in.

You can see this happening with the following code:

def changeme( mylist ):     print locals()  # will show mylist value in function.     mylist = [1,2,3,4];     print locals()  # will show mylist value in function.     print globals()['mylist'] # will show global mylist value     print "Values inside the function: ", mylist     return  

Where you will see the value of mylist change after the assignment in the locals list, but the global reference is still the same.

Answer by Haifeng Zhang for How can this be called Pass By Reference?


mylist = [1,2,3,4] is created inside of changeme() mylist is a local variable, it is not the parameter you passed in even it has the same name as the argument. It doesn't refer to parameter mylist

Answer by Amadan for How can this be called Pass By Reference?


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.

Answer by kindall for How can this be called Pass By Reference?


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.

Answer by viraptor for How can this be called Pass By Reference?


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.

Answer by zondo for How can this be called Pass By Reference?


I never knew the name for it, but according to Amadan, it is "call by sharing". I'll make an analogy to make it easier to understand.

Let's say I have a dog and I name him "Brutus". I take Brutus for a walk and meet my neighbor Sam. Sam doesn't like the name I chose and calls my dog "Dodo". If he puts a knife into Dodo, it of course effects Brutus because they are the same dog. Let's say he doesn't and Billy, another neighbor, is out walking with his dog. Sam changes his mind and decides that Billy's dog is Dodo. If he puts a knife into Dodo, it doesn't effect Brutus because they are different dogs.

Your function is similar. mylist walks over to your function and your function decides to call him mylist, the same name. Your function then decides that [1,2,3,4] is mylist. You have now discarded the original and defined a new list. Your reassignment does not effect the original list.

Answer by mwm314 for How can this be called Pass By Reference?


Python, as far as I'm concerned, is just like Java, in the fact that all functions (methods) are pass-by-value. See this infamous answer. The downfall of "call by sharing" is that it makes you think something different is happening for different types (i.e. mutable types behave differently in function calls than immutable types). This really is not the case, the same thing happens every time you call a function. Also, no textbook I've read mentions the concept, I think pass-by-value and pass-by-reference are much more popular terminology.

How does pass by value work?

It works by copying the "value" which was passed in to the function before modifying it in the function. So, take this example:

my_int = 4  def pass_by_value(value):      value += 1      return value  print pass_by_value(my_int)  print my_int  

this outputs:

5  4  

Observe that the value of my_int didn't change. It stayed at 4 even though the function incremented the value which was passed in to be 5. This is because it was copied. There are several subtleties here which we will return to. Bear with me.

Pass by value on a list

my_list = [1,2,3]  def pass_by_value_list(li):      li.append(4)      return li  print pass_by_value_list(my_list)  print my_list  

this outputs:

[1, 2, 3, 4]  [1, 2, 3, 4]  

What the heck. The value of my_list changed. You JUST SAID ABOVE that pass-by-value copies the value! Therefore, my_list should not have changed!!!

The first example was too subtle. I failed to properly define what "value" was being copied. It turns out, the value that is copied is not the data, but rather, where the data is stored. Typically C/C++ programmers call this a pointer or address. Let's revisit the examples, but modify them a bit to drive home the point.

How does pass by value work? Version 2.0:

my_int = 4  def pass_by_value(value):      print "Address of parameter before += is: ", id(value)      value += 1      print "Address of parameter after += is: ", id(value)      return value  print "Address of parameter outside of the function is: ", id(my_int)  pass_by_value(my_int)  

When I ran this, my output was:

Address of parameter outside of the function is:  40592528  Address of parameter before += is:  40592528  Address of parameter after += is:  40592504  

Looks like the address of the parameter before the += operator was 40592528. This is also the same "value" that the parameter outside the function had! But after the += operator, the "value" changed inside the function! However, that change in address was not propagated outside the function, because the address is pass-by-value. The new address inside the function is 40592504 (different from 40592528, albeit close). Long story short, the += operator makes a new int, and does not operate on the data of the address passed into the function.

Pass by value on a list, Version 2.0:

my_list = [1,2,3]  def pass_by_value_list(li):      print "Address of parameter before .append() is: ", id(li)      li.append(4)      print "Address of parameter after .append() is: ", id(li)      return li  print "Address of parameter outside of the function is: ", id(my_list)  pass_by_value_list(my_list)  

this output:

Address of parameter outside of the function is:  110841160  Address of parameter before .append() is:  110841160  Address of parameter after .append() is:  110841160  

Hey, that's different than the integer case. Looks like all the addresses are the same! Indeed, this is different from the integer case. The append function operates on a list in place, and does not return a new list. This is why you see a change to my_list outside of the function. append modifies the list at the address which was passed in to the function, so we see the data changed everywhere throughout the program. What didn't change, though, was the address.

Observe that:

my_list = [1,2,3]  def dont_change_the_list(li):      li.append(4)      li = []      return li  print dont_change_the_list(my_list)  print my_list  

outputs

[]  [1, 2, 3, 4]  

In other words, the change to the list inside the function wasn't propagated outside the function, even though this seemed to be the behavior we saw before. This is because the statement li = [] changes the address of li, but we copied the address before the function executed. The address of the parameter is the "value" which is copied, and is not possible to change inside of a function. So, this did not change the data in my_list in the main program.

The point: Python always uses pass-by-value semantics on its function calls. The value just happens to be the address of the object which was passed in, not the data of the object which was passed in.


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.