From: John Posner on 15 Feb 2010 14:24 Alf said (2/13/2010 8:34 PM): > Names in Python refer to objects. > > Those references can be copied via assignment. > > That's (almost) all. > > And it provides a very short and neat way to describe pass by sharing. Alf also said (2/13/2010 8:43 PM): > * Steve Howell: > > This thread is interesting on many levels. What is the core > > question that is being examined here? > > I think that regarding the technical it is whether a Python name > refers to an object or not. I maintain that it does, and that the > reference can be copied, and that the semantics of the language > requires this and is defined in terms of this. Steve Holden, > D'Aprano and many others maintain that there are no references, or > that if there are then they're only an implementation aspect, i.e. > that conceiveable one could have an implementation without them. Steve D'Aprano said (2/14/2010 12:13 AM): > That's not to say that the general concept of references (as in "to > refer to") isn't valuable when discussing Python. If you want to say > that (e.g.) following > > x = 1 > > the name "x" refers to (or even points to!) the object 1, my > objections will be mild or non-existent. In that sense, it's probably > impossible to program without some sort of "references": the computer > manipulates variables or objects directly, while we manipulate > characters in source code. The only way to write a program is to use > some abstract thing (a name, an offset, whatever) that refers, in > some fashion, to a collection of bits in the computer's memory. But > to go from that to the idea that (say) x is a pointer does so much > violence to the concept of pointer and has so much room for confusion > that it is actively harmful. I think most of the technical argument in this thread comes down to the various forms of the word *refer*. After execution of this Python statement: x = 5 .... we can use this English-language statement: the name *x* refers to the value *5* (If anyone has more than Steve's "mild" objection, please speak up!) The English-language statement uses the VERB "refers". It is not the same as using the NOUN "reference": *x* is a reference to the value *5* Why not? Because using the NOUN form suggests that you're talking about a particular kind of object in the world Python, as in these statements: *x* is a string *x* is a function *x* is a class But Python does not define *reference* objects -- by which I mean that executing *import types; dir(types)* produces a long list of object-type names, and there's nothing like a "reference" on that list. (I suspect there's a better way to make this "there are no reference objects" argument. Can anyone help?) Amending the statement to: the name *x* is a reference to the value *5* .... doesn't really help matters. Is *x* a NAME or is it a REFERENCE? Looking again at Alf's assertion: > [the core technical question is] whether a Python name > refers to an object or not. I maintain that it does, and that the > reference can be copied, .... and Alf's example (message dated 2/10/2010 5:02 PM): > For example, > > x = s[0] > > accesses the object that s points (refers) to. I believe Alf would characterize this assignment statement as a situation in which "a reference is copied" [using the NOUN form of "refer"]. But no object is copied during execution of this statement. Moreover, saying "a reference is copied" might mislead a Python newbie into thinking that some kind of "reference object" exists that can be copied by Python statements. So it's better to describe the situation using the VERB form of "refer": assigns the name *x* to the object that *s[0]* refers to -John
From: Arnaud Delobelle on 15 Feb 2010 16:25 John Posner <jjposner(a)optimum.net> writes: [...] >> x = s[0] [...] > assigns the name *x* to the object that *s[0]* refers to s[0] does not refer to an object, it *is* an object (once evaluated of course, otherwise it's just a Python expression). -- Arnaud
From: Steven D'Aprano on 15 Feb 2010 18:09 On Mon, 15 Feb 2010 21:25:23 +0000, Arnaud Delobelle wrote: > John Posner <jjposner(a)optimum.net> writes: [...] >>> x = s[0] > [...] >> assigns the name *x* to the object that *s[0]* refers to > > s[0] does not refer to an object, it *is* an object (once evaluated of > course, otherwise it's just a Python expression). Precisely. Treated as an expression, that is, as a string being evaluated by the compiler, we would say that it *refers to* an object (unless evaluation fails, in which case it refers to nothing at all). But treated as whatever you get after the compiler is done with it, that is, post- evaluation, we would say that it *is* an object. This subtle distinction is essentially the difference between a label and the thing that is labeled. -- Steven
From: Alf P. Steinbach on 15 Feb 2010 18:45 * Steven D'Aprano: > On Mon, 15 Feb 2010 21:25:23 +0000, Arnaud Delobelle wrote: > >> John Posner <jjposner(a)optimum.net> writes: [...] >>>> x = s[0] >> [...] >>> assigns the name *x* to the object that *s[0]* refers to >> s[0] does not refer to an object, it *is* an object (once evaluated of >> course, otherwise it's just a Python expression). > > Precisely. Treated as an expression, that is, as a string being evaluated > by the compiler, we would say that it *refers to* an object (unless > evaluation fails, in which case it refers to nothing at all). But treated > as whatever you get after the compiler is done with it, that is, post- > evaluation, we would say that it *is* an object. > > This subtle distinction is essentially the difference between a label and > the thing that is labeled. The main differences between a pure functional language where that view can hold and be reasonable, and a language like Python, are that * Python assignments change which object a name refers to, /at runtime/. - Name binding is run time action, not a compile time action. Without run time binding names couldn't be reassigned. s = 1; s = 2 * Some Python objects are modifiable (a.k.a. mutable). - This is particularly important when two or more names refer to the same object and that object is modified. That is, a simple-minded transfer of concepts from pure functional programming to Python breaks down in these cases[1]. I hope this explanation of exactly where the functional programming enthusiasts here go wrong can be of help to readers of the thread, although I've given up hope on those holding the functional programming view (since I'm only human, and even the Gods contend in vain against that sort of thing). Cheers & hth., - Alf Notes: [1] Steven D'Aprano's focus on compilation rather than execution mainly ignores the first point, that a name in given a statement in a loop, say, can refer to different objects in different loop iterations. Happily the Python language specification explains binding as a run-time action. Binding is not a compile time action in Python, it is a run-time action, and can bind a given name in a given statement within the same routine execution, to different objects, and the language specification of course uses the phrase "refers to" to explain the situation after a run time binding.
From: John Posner on 15 Feb 2010 19:33
On 2/15/2010 6:09 PM, Steven D'Aprano wrote: > On Mon, 15 Feb 2010 21:25:23 +0000, Arnaud Delobelle wrote: > >> John Posner<jjposner(a)optimum.net> writes: [...] >>>> x = s[0] >> [...] >>> assigns the name *x* to the object that *s[0]* refers to >> >> s[0] does not refer to an object, it *is* an object (once evaluated of >> course, otherwise it's just a Python expression). > > Precisely. Treated as an expression, that is, as a string being evaluated > by the compiler, we would say that it *refers to* an object (unless > evaluation fails, in which case it refers to nothing at all). But treated > as whatever you get after the compiler is done with it, that is, post- > evaluation, we would say that it *is* an object. > > This subtle distinction is essentially the difference between a label and > the thing that is labeled. Is this your only quibble with my writeup? If, so, I'm gratified. And your objections make perfect sense. Still, I'll attempt to justify my phrasing. I was originally going to write: assigns the name *x* to the object that THE NAME *s[0]* refers to .... but I didn't want to start a distracting argument on the use of the phrase *the name* to describe the 4-char string *s[0]*. So now I'll try to (briefly) make my case. Yes, it might be more correct to say that *s[0]* is an expression (equivalent to the more obvious expression *s.__getitem__(0)*). But in common usage, the 4-char string *s[0]* _behaves_ like a name. If you accept this viewpoint, the story on Python assignment statements becomes quite simple ... Syntactic sugar aside, there are only two kinds of assignment statements: 1. NAME = EXPRESSION The EXPRESSION creates a new object, and the NAME is assigned to that object. Examples: x = x + 1 obj = MyClass(1, 2, "red") mywordlist = mysentence.split() 2. NAME2 = NAME1 No new object is created. NAME2 becomes another name (an "alias") for the existing object that currently has NAME1 assigned to it. Examples: y = x s[0] = s[42] mydict["spamwich"] == this_sandwich obj.color = MYCOLORS.LTGREEN This viewpoint might fail in advanced areas of Python programming: properties/descriptors, double-underscore methods, etc. But in my own day-to-day usage (admittedly, I'm a hobbyist Python programmer, not a professional), it's never failed me to think this way: * A dict is a collection of user-devised names, each of which is assigned to an object. * A list/tuple is an interpreter-maintained collection of integer names (0, 1, 2, ...), each of which is assigned to an object. * A class instance is very much like a dict. Tx, John |