list.sort()

Michael Chermside mcherm at destiny.com
Sun Jun 17 14:10:36 EDT 2001


> I know the sort-method on lists changes the list in-place and doesn't
> return anything, but I'm still confused.
> 
> Take these examples:
> 
> >>> l = [4,3,2]
> >>> l = l
> >>> l
> [4, 3, 2]
> 
> The list is unchanged, even after assigning it to itself. But:
> 
> >>> l = l.sort()
> >>> l
> >>> print l
> None
> 
> If we split the problem into parts, "l.sort()" sorts l and it becomes
> [2,3,4]. I expected it to be [2,3,4] after assigning it to itself (after
> it got sorted), but the list seem to got deleted instead. I don't like
> this behaviour, at all.

Okay, I think I can answer this one. Suppose that you did the following:

>>> l = [4,3,2]
>>> l = l.getLength()
>>> print l

Well, first of all, you'd get an error because there's no method of Lists
called "getLength()", but if there WERE, you'd probably expect this to
change l from the list [4,3,2] to the number 3. The idiom "l = l.func()"
changes l to whatever l.func() returns, REGARDLESS of whether or not 
calling .func() has side-effects like modifying the list.

So consider your code:

>>> l = [4,3,2]
>>> l = l.sort()
>>> print l

What does "l.sort()" return? Why, like all functions that don't really
have a meaningful "return value" it returns "None". And so l gets set to
None (it is NOT deleted... just set to None).

What you really wanted is this:

>>> l = [4,3,2]
>>> l.sort()
>>> print l
[2, 3, 4]


> Why does Python behave like this? Why does sort() change lists
> _in-place_, instead of returning a list?

Now THAT is a really excellent question. Because there are two reasonable
ways that Guido COULD have done it. The correct idiom could (sensibly) be 
either:

>>> l.sort()   # Idiom 1: correct idiom

or

>>> l = l.sort()  # Idiom 2: incorrect idiom

The second idiom, which Guido DIDN'T chose has certain advantages. The
biggest advantage is that it doesn't modify the original list. This is
particularly useful in functional style programming, and you can see how
it would work in the follow [hypothetical] snippet:

NOT_REAL>>> list = [4,3,2]
NOT_REAL>>> newlist = list.sort()
NOT_REAL>>> newlist
[2, 3, 4]
NOT_REAL>>> list
[4, 3, 2]

Well... that's a cool feature! So why on earth did Guido pick idiom 1?
Well, the very feature that we're lauding here is the source of the
problem. Because idiom 2 would require the that the original list not
be changed, a whole new list would have to be created. This would wind
up taking 2x as much memory!

The decision was made that requiring the use of 2x as much memory each
time a list was sorted was just too much overhead to impose on everyone.
But never fear! If this is how you WANT to work, then it only requires
4 extra lines of code!!! The following demonstrates a simple function
to return a sorted version of a list without modifying the original:

>>> def sortlist(list):
	newlist = list[:]
	newlist.sort()
	return newlist

>>> l = [4,3,2]
>>> l = sortlist(l)
>>> l
[2, 3, 4]

Have fun!

-- Michael Chermside




More information about the Python-list mailing list