On Tue, 07 Jul 2009 20:04:46 +0000, kj wrote: > I'm having a hard time coming up with a reasonable way to explain > certain things to programming novices.
[...] > Or consider this one: > >>>> ham = [1, 2, 3, 4] >>>> spam = (ham,) >>>> spam > ([1, 2, 3, 4],) >>>> spam[0] is ham > True >>>> spam[0] += [5] > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > TypeError: 'tuple' object does not support item assignment >>>> ham += [5] >>>> spam > ([1, 2, 3, 4, 5, 5],) >>>> >>>> > What do you say to that? That one surely is very straight forward. Just like the exception says, tuples don't support item assignment, so spam[0] += [5] is not allowed. But just because you have put a list inside a tuple doesn't mean the list stops being a list -- you can still append to the list, which is what ham += [5] does. So spam is unchanged: it is still the one-item tuple containing a list. It is just that the list has now been modified. This is only troublesome (in my opinion) if you imagine that tuples are somehow magical "frozen-lists", where the contents can't be modified once created. That's not the case -- the tuple itself can't be modified, but the objects inside it remain ordinary objects, and the mutable ones can be modified. The thing to remember is that the tuple spam doesn't know anything about the *name* ham -- it knows the object referred to by the name ham. You can modify the name, and nothing happens to the tuple: >>> spam ([1, 2, 3, 4, 5],) >>> ham = [5] >>> spam ([1, 2, 3, 4, 5],) Or if you prefer: >>> ham = spam[0] # label the list inside spam as 'ham' >>> ham += [6] # modify the list labelled as 'ham' >>> spam ([1, 2, 3, 4, 5, 6],) >>> pork = ham # create a new label, 'pork', and bind it to the same list >>> del ham # throw away the label 'ham' >>> pork += [7] # modify the list labelled as 'pork' >>> spam ([1, 2, 3, 4, 5, 6, 7],) It's all about the objects, not the names. -- Steven -- http://mail.python.org/mailman/listinfo/python-list