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

Reply via email to