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!
It sorts the list in place. Can you use sorted(item_list)? -Ryan Birmingham On 26 February 2017 at 22:07, qhlonline <qhlonline@163.com> wrote:
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!
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
On Sun, Feb 26, 2017 at 10:23 PM qhlonline <qhlonline@163.com> wrot
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!
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:
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.
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.
Now list.sort() returns nothing, so that I can NOT write code like this:
res = {item: func(item) for item in item_list.sort()}
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
On 28/02/17 09:13 PM, Steven D'Aprano wrote:
On Mon, Feb 27, 2017 at 11:07:33AM +0800, qhlonline wrote:
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. 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.
Now list.sort() returns nothing, so that I can NOT write code like this:
res = {item: func(item) for item in item_list.sort()} 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}
Stateful functions?
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 Mon, Feb 27, 2017 at 11:07:33AM +0800, qhlonline wrote:
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.
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.
Now list.sort() returns nothing, so that I can NOT write code like this:
res = {item: func(item) for item in item_list.sort()}
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 _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
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>:
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 _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
Cf. https://martinfowler.com/bliki/CommandQuerySeparation.html But:
l = [1,2,3] l.pop() 3 l [1, 2]
=> Not so true. S. On Wed, Mar 1, 2017 at 11:10 AM, Stephan Houben <stephanh42@gmail.com> wrote:
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>:
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 _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
-- 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
On 1 Mar 2017, at 10:26, Stéfane Fermigier <sf@fermigier.com> wrote:
Cf. https://martinfowler.com/bliki/CommandQuerySeparation.html <https://martinfowler.com/bliki/CommandQuerySeparation.html>
But:
l = [1,2,3] l.pop() 3 l [1, 2]
=> Not so true.
S.
This is naturally a different circumstance: pop must return the element it popped, otherwise it would just be del. Surely you aren’t suggesting that pop should return self? Cory
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:
On 1 Mar 2017, at 10:26, Stéfane Fermigier <sf@fermigier.com> wrote:
Cf. https://martinfowler.com/bliki/CommandQuerySeparation.html
But:
l = [1,2,3] l.pop() 3 l [1, 2]
=> Not so true.
S.
This is naturally a different circumstance: pop must return the element it popped, otherwise it would just be del. Surely you aren’t suggesting that pop should return self?
Cory
-- 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
From my experience teaching Python to non-programmers, it's a huge hurdle/nightmare to teach functions/methods that modify objects in-place vs. return a value that must be reassigned. Behold Pandas's DataFrame's sort method, which has an optional `in_place` argument that defaults to *False*, which despite being a method that looks like mylist.sort(), works differently from the method on lists, but more like the sorted *function*, arrrgh! That was a fun session...
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:
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:
On 1 Mar 2017, at 10:26, Stéfane Fermigier <sf@fermigier.com> wrote:
Cf. https://martinfowler.com/bliki/CommandQuerySeparation.html
But:
l = [1,2,3] l.pop() 3 l [1, 2]
=> Not so true.
S.
This is naturally a different circumstance: pop must return the element it popped, otherwise it would just be del. Surely you aren’t suggesting that pop should return self?
Cory
-- 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
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
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
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 1 March 2017 at 19:38, Serhiy Storchaka <storchaka@gmail.com> wrote:
On 01.03.17 11:31, Paul Moore 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))
Or just sorted(lst, reverse=True).
Indeed. Which illustrates nicely why learning Python's approach to doing things rather than translating idioms from other languages will get cleaner code. Paul
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