Joe Strout wrote: > On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote: [much blether] >>> 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. > In [8]: def foo(x): ...: x += [42] ...:
In [9]: a = [1, 2, 3] In [10]: foo(a) In [11]: a Out[11]: [1, 2, 3, 42] In [12]: def ffoo(x): ....: x.append(43) ....: In [13]: ffoo(a) In [14]: a Out[14]: [1, 2, 3, 42, 43] In [15]: def fffoo(a): ....: a = a + [42] ....: In [16]: fffoo(a) In [17]: a Out[17]: [1, 2, 3, 42, 43] So, is it call by reference or not? Does that depend on the implementation of specific operators? You problem seems to be that you ar still stuck with the notion of a name as a reference to a specific area of memory. Which it's not, excepting only if you want to consider the area of memory that holds a reference to some value. In the case of lists, a = a + [something] rebinds a, while a += [something] doesn't. So where does that leave you? > 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. > Be careful though: In [18]: a = 42 In [19]: id(a) Out[19]: 14237932 In [20]: a += 1 In [21]: id(a) Out[21]: 14237920 In [22]: a = [] In [23]: id(a) Out[23]: 2140206636 In [24]: a += [42] In [25]: id(a) Out[25]: 2140206636 In other words, the behavior of augmented operations depends on whether the reference is to a mutable or an immutable value. >> 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". > It might be simpler to say "Change this name to be a reference to that value", or "Change this name to be a reference to the [result of evaluating the] expression on the RHS". Or indeed, "Change the content of that container element to be a reference to the [result of evaluating the] expression on the RHS" > 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.) > If you mean it's a reference assigment, of course it is. That's what he was trying to say (I believe). But in C, for example, int i; i = 42; actually stores the value 42 in the location associated with the name c. Quite different from int *i; i = &42; [Is that even valid C?] That's almost what Python does with i = 42 >>> 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! > 40 Mb! You were lucky! Etc., etc., [drools into beard.] >>> 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. > Python's assignment semantics (as opposed to its "object handling, a term for which I have no referent) are not the same as those of, say C. I believe they are pretty much the same ass those of Icon, another non-standard interpreted language. There are close similarities between Python's names and C reference variables, but the semantics are not exactly parallel. People here don't describe Python as different just because they *want* it to be different. Python acknowledges intellectual debts to many languages, none of which is exactly like it. regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list