On 2007-08-12, Alex Martelli <[EMAIL PROTECTED]> wrote: > Neil Cerutti <[EMAIL PROTECTED]> wrote: > ... >> OK, I've thought about this some more and I think the source >> of my confusion was I thought assignment in Python meant >> binding a name to something, not mutating an object. But in >> the case of augmented assignment, assignment no longer means >> that? > > "Plain" assignment *to a plain name* does mean "binding a name" > (the LHS) to "something" (the RHS). > > Other assignments (ones that are not "plain" assignments to > names) may have different meanings. For example: > >>>> class act(object): > ... def __init__(self, c): self._c = c > ... def getC(self): return self._c > ... def setC(self, *ignore): self._c += 1 > ... c = property(getC, setC) > ... >>>> x = act(0) >>>> x.c > 0 >>>> x.c = 23 >>>> x.c > 1 > > Here's an example where a plain assignment (to an attribute of x, not to > a plain name) obviously DOESN'T mean "binding a name to something": the > "something" (the RHS) is completely ignored, so the plain assignment is > mutating an object (x) and not binding any name to anything.
That's enlightening. I hadn't considered the implications of generalizing assignment to names with assignment to qualified names. > Plain assignments to items and slices can also often be best > seen as "mutating an object" (the one being indexed or sliced > on the LHS) rather than "binding a name". For example: > >>>> l=list('ciao') >>>> l[1:3]='app' >>>> l > ['c', 'a', 'p', 'p', 'o'] That example makes me feel ashamed for not thinking of it, since I use the slicing assignment all the time and it's "obviously" not a binding construct. > If I was teaching Python and came upon this example, I would > definitely not try to weaselword the explanation of what's > going on in terms of "binding a name" (or several ``names'', > including ``rebinding" a new ``name'' l[4] to the 'o' that was > previously ``bound'' to l[3], etc:-): it's just orders of > magnitudes simpler to explain this as "mutating an object", > namely the list > > I take almost 3 pages in "Python in a Nutshell" (47 to 49 in > the second edition) to summarily explain every kind assignment > -- and that's in a work in which I've tried (successfully, I > believe from reviews) to be very, *VERY* concise;-). > > Summarizing that summary;-), a plain assignment to an identifier binds > that name; a plain assignment to an attribute reference x.y asks object > x (x can be any expression) to bind its attribute named 'y'; a plain > assignment to an indexing x[y] (x and y are arbitrary expressions) asks > object x to bind its item indicated by the value of y); a plain > assignment to a slicing is equivalent to the plain assignment to the > indexing with an index of slice(start, stop, stride) [[slice is a Python > builtin type]]. > > Plain assignment to an identifier "just happens"; all other cases of > plain assignment are requests to an object to bind one or more of its > attributes or items (i.e., requests for specific mutations of an object) > -- as for, say any method call (which might also be a request for some > kind of mutation), the object will do whatever it pleases with the > request (including, perhaps, "refusing" it, by raising an exception). > > Then we get into unpacking assignments and augmented > assignments, but I don't really want to write two more pages > worth of summary...;-). Thanks very much for taking the time to help clear up my erroneous model of assignment in Python. I'd taken a conceptual shortcut that's not justified. -- Neil Cerutti -- http://mail.python.org/mailman/listinfo/python-list