suggestion about the sort() function of the list instance

Hi, all I have a suggestion that, the sort() member method of the list instance, should return the 'self' as the result of list.sort() call. Now list.sort() returns nothing, so that I can NOT write code like this: res = {item: func(item) for item in item_list.sort()} It feels bad. Regards!

On Sun, Feb 26, 2017 at 10:23 PM qhlonline <qhlonline@163.com> wrot
list.sort() does not return anything on purpose, to remind you that it operates by side effect (i.e. that calling list.sort() mutates the list in-place). If you want it to return the list, use sorted() to get a copy of the list. Also, for your specific example, I wouldn't use a comprehension in the first place. I'd probably do something like this: item_list.sort() res = dict(zip(item_list, map(func, item_list))) But sorting the item_list is pointless in this case, since dictionaries are unordered [1], so the sorting has no real effect in this case, other than the fact that the list is now sorted for the benefit of subsequent code, if that should be relevant. [1] Dictionaries are ordered in CPython 3.6, but this behavior cannot be relied upon, as doing so means your code won't work on older versions of CPython, nor is it guaranteed to work in other implementations of Python 3.6.

On Mon, Feb 27, 2017 at 11:07:33AM +0800, qhlonline wrote:
Having list.sort() and list.reverse() return self is a perfectly good design. The advantage is you can write things like this: list.sort().reverse() but the disadvantage is that it may fool people into thinking it returns a *copy* of the list. Python avoids that trap by returning None, so that you cannot write: sorted_items = items.sort() but instead people write: items = items.sort() so it seems that whatever we do, it will confuse some people.
What is the purpose of the sort? Because dicts are unordered, the results will be no different if you just write: d = {item: func(item) for item in item_list} -- Steve

My code example is not proper, Yes, may be this is better: list.sort().revers(). Other languages do this differently. JavaScript may return the sorted, while C++ STL returns nothing. I think that it maybe more important to let user have good knowledge about this function then to have fluent code on some occasions. I prefer to draw back this suggestion. Regards! At 2017-03-01 08:13:39, "Steven D'Aprano" <steve@pearwood.info> wrote:

On 1 March 2017 at 01:31, qhlonline <qhlonline@163.com> wrote:
My code example is not proper, Yes, may be this is better: list.sort().revers(
We can already do this - reversed(sorted(lst)) This is a long-established design decision in Python. It would need a *very* compelling use case to even think about changing it. Paul

It's even in the Programming FAQ: "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." Stephan 2017-03-01 10:31 GMT+01:00 Paul Moore <p.f.moore@gmail.com>:

Cf. https://martinfowler.com/bliki/CommandQuerySeparation.html But:
=> Not so true. S. On Wed, Mar 1, 2017 at 11:10 AM, Stephan Houben <stephanh42@gmail.com> wrote:
-- Stefane Fermigier - http://fermigier.com/ - http://twitter.com/sfermigier - http://linkedin.com/in/sfermigier Founder & CEO, Abilian - Enterprise Social Software - http://www.abilian.com/ Chairman, Free&OSS Group / Systematic Cluster - http://www.gt-logiciel-libre.org/ Co-Chairman, National Council for Free & Open Source Software (CNLL) - http://cnll.fr/ Founder & Organiser, PyData Paris - http://pydata.fr/ --- “You never change things by fighting the existing reality. To change something, build a new model that makes the existing model obsolete.” — R. Buckminster Fuller

Definitively not, just like M. Fowler: "Meyer likes to use command-query separation absolutely, but there are exceptions. Popping a stack is a good example of a query that modifies state. Meyer correctly says that you can avoid having this method, but it is a useful idiom. So I prefer to follow this principle when I can, but I'm prepared to break it to get my pop." 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. S. On Wed, Mar 1, 2017 at 6:23 PM, Cory Benfield <cory@lukasa.co.uk> wrote:
-- Stefane Fermigier - http://fermigier.com/ - http://twitter.com/sfermigier - http://linkedin.com/in/sfermigier Founder & CEO, Abilian - Enterprise Social Software - http://www.abilian.com/ Chairman, Free&OSS Group / Systematic Cluster - http://www.gt-logiciel-libre.org/ Co-Chairman, National Council for Free & Open Source Software (CNLL) - http://cnll.fr/ Founder & Organiser, PyData Paris - http://pydata.fr/ --- “You never change things by fighting the existing reality. To change something, build a new model that makes the existing model obsolete.” — R. Buckminster Fuller

I think for consistency, having object methods that can act in-place (semantics like mylist.pop, mylist.append are nice as Stéfane suggests) only act in-place, and functions return a new object for reassignment would help new users. Maybe I'm teaching it poorly, suggestions welcome. Nick On Wed, Mar 1, 2017 at 11:26 AM, Stéfane Fermigier <sf@fermigier.com> wrote:

On 3/1/2017 12:26 PM, Stéfane Fermigier wrote:
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

Stéfane Fermigier wrote:
Cf. https://martinfowler.com/bliki/CommandQuerySeparation.html
Python's convention is less extreme than this, since it only applies to methods that, under the conventions of some other languages, would return self to facilitate chaining. There's no rule against a mutating method returning some other value if that's convenient. -- Greg

On Sun, Feb 26, 2017 at 10:23 PM qhlonline <qhlonline@163.com> wrot
list.sort() does not return anything on purpose, to remind you that it operates by side effect (i.e. that calling list.sort() mutates the list in-place). If you want it to return the list, use sorted() to get a copy of the list. Also, for your specific example, I wouldn't use a comprehension in the first place. I'd probably do something like this: item_list.sort() res = dict(zip(item_list, map(func, item_list))) But sorting the item_list is pointless in this case, since dictionaries are unordered [1], so the sorting has no real effect in this case, other than the fact that the list is now sorted for the benefit of subsequent code, if that should be relevant. [1] Dictionaries are ordered in CPython 3.6, but this behavior cannot be relied upon, as doing so means your code won't work on older versions of CPython, nor is it guaranteed to work in other implementations of Python 3.6.

On Mon, Feb 27, 2017 at 11:07:33AM +0800, qhlonline wrote:
Having list.sort() and list.reverse() return self is a perfectly good design. The advantage is you can write things like this: list.sort().reverse() but the disadvantage is that it may fool people into thinking it returns a *copy* of the list. Python avoids that trap by returning None, so that you cannot write: sorted_items = items.sort() but instead people write: items = items.sort() so it seems that whatever we do, it will confuse some people.
What is the purpose of the sort? Because dicts are unordered, the results will be no different if you just write: d = {item: func(item) for item in item_list} -- Steve

My code example is not proper, Yes, may be this is better: list.sort().revers(). Other languages do this differently. JavaScript may return the sorted, while C++ STL returns nothing. I think that it maybe more important to let user have good knowledge about this function then to have fluent code on some occasions. I prefer to draw back this suggestion. Regards! At 2017-03-01 08:13:39, "Steven D'Aprano" <steve@pearwood.info> wrote:

On 1 March 2017 at 01:31, qhlonline <qhlonline@163.com> wrote:
My code example is not proper, Yes, may be this is better: list.sort().revers(
We can already do this - reversed(sorted(lst)) This is a long-established design decision in Python. It would need a *very* compelling use case to even think about changing it. Paul

It's even in the Programming FAQ: "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." Stephan 2017-03-01 10:31 GMT+01:00 Paul Moore <p.f.moore@gmail.com>:

Cf. https://martinfowler.com/bliki/CommandQuerySeparation.html But:
=> Not so true. S. On Wed, Mar 1, 2017 at 11:10 AM, Stephan Houben <stephanh42@gmail.com> wrote:
-- Stefane Fermigier - http://fermigier.com/ - http://twitter.com/sfermigier - http://linkedin.com/in/sfermigier Founder & CEO, Abilian - Enterprise Social Software - http://www.abilian.com/ Chairman, Free&OSS Group / Systematic Cluster - http://www.gt-logiciel-libre.org/ Co-Chairman, National Council for Free & Open Source Software (CNLL) - http://cnll.fr/ Founder & Organiser, PyData Paris - http://pydata.fr/ --- “You never change things by fighting the existing reality. To change something, build a new model that makes the existing model obsolete.” — R. Buckminster Fuller

Definitively not, just like M. Fowler: "Meyer likes to use command-query separation absolutely, but there are exceptions. Popping a stack is a good example of a query that modifies state. Meyer correctly says that you can avoid having this method, but it is a useful idiom. So I prefer to follow this principle when I can, but I'm prepared to break it to get my pop." 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. S. On Wed, Mar 1, 2017 at 6:23 PM, Cory Benfield <cory@lukasa.co.uk> wrote:
-- Stefane Fermigier - http://fermigier.com/ - http://twitter.com/sfermigier - http://linkedin.com/in/sfermigier Founder & CEO, Abilian - Enterprise Social Software - http://www.abilian.com/ Chairman, Free&OSS Group / Systematic Cluster - http://www.gt-logiciel-libre.org/ Co-Chairman, National Council for Free & Open Source Software (CNLL) - http://cnll.fr/ Founder & Organiser, PyData Paris - http://pydata.fr/ --- “You never change things by fighting the existing reality. To change something, build a new model that makes the existing model obsolete.” — R. Buckminster Fuller

I think for consistency, having object methods that can act in-place (semantics like mylist.pop, mylist.append are nice as Stéfane suggests) only act in-place, and functions return a new object for reassignment would help new users. Maybe I'm teaching it poorly, suggestions welcome. Nick On Wed, Mar 1, 2017 at 11:26 AM, Stéfane Fermigier <sf@fermigier.com> wrote:

On 3/1/2017 12:26 PM, Stéfane Fermigier wrote:
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

Stéfane Fermigier wrote:
Cf. https://martinfowler.com/bliki/CommandQuerySeparation.html
Python's convention is less extreme than this, since it only applies to methods that, under the conventions of some other languages, would return self to facilitate chaining. There's no rule against a mutating method returning some other value if that's convenient. -- Greg
participants (13)
-
Cory Benfield
-
Greg Ewing
-
Jonathan Goble
-
Nick Timkovich
-
Paul Moore
-
qhlonline
-
Ryan Birmingham
-
Serhiy Storchaka
-
Soni L.
-
Stephan Houben
-
Steven D'Aprano
-
Stéfane Fermigier
-
Terry Reedy