Something in the function tutorial confused me.

Neil Cerutti horpner at yahoo.com
Mon Aug 13 09:37:26 EDT 2007


On 2007-08-12, Alex Martelli <aleax at mac.com> wrote:
> Neil Cerutti <horpner at yahoo.com> 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



More information about the Python-list mailing list