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