[Python-ideas] suggestion about the sort() function of the list instance
Terry Reedy
tjreedy at udel.edu
Wed Mar 1 16:42:34 EST 2017
On 3/1/2017 12:26 PM, Stéfane Fermigier wrote:
> What I wanted to point out is that the paragraph quoted by Stephan ("In
> general in Python (and in all cases in the standard library) a method
> that mutates an object will return None to help avoid getting the two
> types of operations confused. So if you mistakenly write y.sort()
> thinking it will give you a sorted copy of y, you’ll instead end up with
> None, which will likely cause your program to generate an easily
> diagnosed error.") doesn't seem to be true in this case.
What is true AFAIK, is that stdlib collection mutation methods never
return 'self'. There is usually no need to return self as one will
already have a reference to the collection.
A disadvantage (to some) of this policy is to not be able to chain calls
so neatly. (But Python is not about writing everything as one-line
expressions.)
An advantage of not returning 'self' when mutating is the possibility of
returning something from the collection without resorting to returning
tuples. While most mutation methods return None, there are exceptions
where the primary purpose of the mutation is to return something other
than self and None. The two that come to mind are various
mutable_collection.pop methods (sometimes with a suffix) and
iterator.__next__ ('pop front'). Note that an iterator is a mutable
virtual collection, which may or may not be dependent on a concrete
collection object that is not mutated by the iteration.
In functional languages, iteration through a sequence 'alist' may be
done something as follows, with pair assignment.
a_it = alist
while a_it:
a, a_it = first(a_it), rest(a_it)
process(a)
To be time efficiency, a_list must be a linked list, so that all
tail-slices (returned by rest), already exist. While this can be done
in Python, I generally prefer Python's iteration protocol. The closest
equivalent to the above is the admittedly clumsy
a_it = iter(alist)
while True:
try:
a = next(a_it)
except StopIteration:
break
process(a)
But with the boilerplate code hidden, this becomes one of Python's gems.
for a in alist:
process(a)
The above works for iterable linked lists but is MUCH more flexible and
general.
--
Terry Jan Reedy
More information about the Python-ideas
mailing list