On Nov 4, 2008, at 3:54 PM, Steven D'Aprano wrote:

At the level of Python code, Python operates on *objects*. When you call a function with an argument, the argument (an object) is NOT copied, it
is passed to the function. If you mutate the argument inside the
function, you are changing the object and the caller will see the
mutation: this is just like call-by-reference, and unlike call-by- value.

And here is the key bit that you are missing.

When you pass a reference to an object to a function, and then mutate the object, then OF COURSE the caller (as well as any other holders of a reference to that object) will see the mutation. This is true in ANY language. Pick your language, and I will demonstrate it. Here are a few to get us started (assume a class "Person" with an attribute "zipcode"):

C++:
void foo(PersonPtr who) {
        who->zipcode = 12345;
}

Java:
void foo(Person who) {
        who.zipcode = 12345;
}

REALbasic/VB.Net:
Sub foo(ByVal who as Person)
        who.zipcode = 12345
End Sub

Python:
def foo(who):
        who.zipcode = 12345


So please clarify your position by identifying which statement applies:

1. You don't believe that these languages are actually passing by value.
2. You don't believe these examples are mutating an object.
3. You don't believe these mutations can be seen by the caller after the call. 4. You now see how a mutating an object within a function tells you NOTHING about how the reference to that object was passed. 5. You see that the first three languages above are passing a reference by value and using that to mutate and object, yet for reasons still mysterious, the Python example (which has exactly the same behavior) must be doing something different.

I hate being confrontational, but you're the one accusing me of ignoring evidence against my "pet theory" (by which you mean the standard definitions of c-b-v and c-b-r). Let's see what you do with this evidence that directly contradicts yours.

Sigh.

But if you assign a different object to the argument name, the caller
does NOT see the change, which is just like call-by-value.

This at least you have correct.

So depending
on what type of object the argument is, and depending on what you do
inside the function, you get something that looks rather like call-by-
value or call-by-reference semantics.

But no, you don't, as I just demonstrated above (and explained a week ago at <http://www.strout.net/info/coding/valref/>). You always have call-by-value semantics. The semantics are exactly the same as in any other language with anything resembling an object reference, including those with both "ByVal" and "ByRef" modes (except that there is no equivalent to the "ByRef" mode in Python).

But what the Python VM does is the
same no matter what you do: Python's calling model is different from
either byval or byref.

No, it's exactly byval.  No.  Different.  In.  Any.  Way.

Let's tackle it this way: one of the following must be true for your belief system to prop itself up at all:

1. Python's behavior is different from Java, REALbasic, VB.NET, and C++.
...or...
2. None of those languages mentioned use call-by-value.

In fact both of these statements are false, but we can cut our time and effort in half if you will just select the one that you believe to be true, so we can focus on that. Which is it?

Thanks,
- Joe

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to