On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote:
On Thu, 16 Oct 2008 21:19:28 -0600, Joe Strout <[EMAIL PROTECTED]>
declaimed the following in comp.lang.python:
Now that IS mysterious. Doesn't calling a function add a frame to a
stack? And doesn't that necessitate copying in values for the
variables in that stack frame (such as 'x' above)? Of course we're
No -- it copies the /reference/ to the object containing the value.
The reference to the object IS the value of an object reference
variable. So good, parameters are passed ByVal in Python as they
appear to be, and as is the default in every other modern language.
Just as assignment transfers the reference to the RHS object to the
name
shown on the LHS.
Assignment copies the RHS value to the LHS variable. In the case of
an object reference, the value copied is, er, an object reference.
The semantics here appear to be exactly the same as Java or REALbasic
or any other modern language: variables are variables, and parameters
are local variables with called by value, and it just so happens that
some values may be references to data on the heap.
ALL "values" are references to data in Python -- but some of those
values are immutable objects so any operation performed on them
creates
new objects, and the assignment is of a new reference.
OK, that part is a little different from most languages -- not in the
way objects are treated, but in the fact that even simple values like
integers are wrapped in objects. But since those are immutable
objects, this is mostly an internal implementation detail.
For object references (including the mutable ones that may treat
people up), Python's behavior is no different from any other language.
(Answer: neither. They are call by name.)
I have no idea what that means. They're call by value as far as I
can
tell. (Even if the value may happen to be a reference.)
Technically, as I recall the definition of "call by name", they
aren't that either. ...
Call by name, then, acted as a macro expansion wherever the argument
was referenced in the called function.
Thanks for that explanation. Clearly that's not what's going on in
Python.
Side question, for my own education: *does* Python have a "ByRef"
parameter mode?
As far as I'm concerned -- everything is "by ref" in Python...
No, a "by ref" parameter would mean that this:
def foo(ByRef x):
x = x + [42]
a = [1,2,3]
foo(a)
...would result in a = [1,2,3,42]. You would only be able to pass a
simple variable (not an expression or literal) to foo, and the 'x'
inside foo would not be a local variable, but an alias of whatever
variable was passed in. Thus any assignments to it would affect the
original variable that was passed in.
But if Python has any such feature, I'm not aware of it. Certainly
the default behavior is to pass everything (even object references) by
value. Assignments made to them don't affect anything else.
Mutation of an object is never a bare LHS... It is either a method
call of the name
alist.append()
or a drill-down going inside the object
alist[2] = something
anobject.attribute = something
adict["key"] = something
Or, use of one of the compound operators like +=. That's the only
real "gotcha" in Python to somebody coming from another language; you
might naively expect that x += y is the same as x = x+y, but in Python
this is not generally the case; instead += is a mutation operator,
like the examples you show above.
But every language I've used (many: FORTRAN, C, C++, BASIC, VB,
Assembly, COBOL, Ada...) treats "variable" as "name of fixed
location in
memory" and assignment to the variable means "replace the contents of
the location of memory associated with this name with the contents of
memory to which that name (may be anonymous in the case of an
expression) is associated by copying the contents from there to here"
That's what Python does too. It just so happens that the fixed
location in memory contains an object reference. No difference here
between Python's object references VB.NET's object references, C++
pointers, Java object references, etc. etc.
Python, OTOH, ALWAYS handles assignment as "change the memory
association of this name to be the same as that name".
What does that mean, exactly? It means: "replace the contents (i.e.
object reference) of the memory location associated with this name
with the contents (i.e. object reference) of the memory to which that
name is associated by copying the contents from there to here."
It's the exact same thing. (And exactly the same as in any other
language.)
No, but if we define them in the standard way, and point out that
Python variables behave exactly like variables in other languages,
then that IS helpful.
But they don't...
They really, really do.
But it's not at all surprising with lists and dicts and objects --
every modern language passes around references to those, rather than
the data themselves, because the data could be huge and is often
changing size all the time. Storing the values in a variable would
just be silly.
In most all of those languages, one has to explicitly differentiate
the the difference between a copy and a reference.
Only if you're thinking of languages from 20 years ago or more. Even
in C++, while there is a different bit of kludgy syntax for object
"references" (because they're mere pointers), it's the standard to use
such pointers everywhere that objects are handled. Java cleaned up
that kludginess by replacing the pointers with proper references, as
did VB.NET, REALbasic, probably Ruby, and of course Python.
And even that is not
assured... As I recall, nothing in the Ada language reference forbids
implementing an "in out" procedure parameter from being implemented
via
copy-in/copy-out semantics rather than via reference.
Hah, well probably so. Ada even predates me, and I'm not all that
young anymore!
Hmm... I bet you're over 30. :) So am I, for that matter, so I can
remember when people had to learn "pointers" and found it difficult.
Bah... The roots of I/O in Pascal required pointer dereferencing.
Hey, I remember Pascal... that was the language used on the Apple
IIGS, back when I was in junior high. I also remember spending $800
for a 40MB hard drive for it. Ah, those were the days!
So, if the semantics are all the same, I think it's helpful to use
the
standard terminology.
But, it seems, you are the only one arguing that "the semantics are
all the same"... Doesn't that suggest that they aren't the same?
No, it suggests to me that there's a lot of confusion in the Python
community. :) It appears as though people either (a) really want to
think that Python's object handling is special and unique for
emotional reasons, or (b) are comparing it to really ancient languages
that didn't have any notion of objects and object references. This
has led to making up new terminology and spreading confusion. I'm
coming back to Python from almost a decade of working with other
modern languages (including implementing the compiler for one of
them), and I don't see any difference at all between Python's object
handling and those.
Best,
- Joe
--
http://mail.python.org/mailman/listinfo/python-list