[Tutor] decomposing a problem

Avi Gross avigross at verizon.net
Tue Dec 25 22:25:50 EST 2018


Alan,

Your thoughts were helpful and gave me a hint.

Just an idea. What if you sub-classed an object type like list with a name
like chainable_list?

For most things it would be left alone. But if you isolated specific named
methods like sort() and reverse() you could over-ride them with the same
name or a new name.

If you override the function, you need to call list.sort() with whatever
arguments you had passed and then return this. If you choose a new name,
call this.sort() and then return this.

I tried it and it seems to work fine when I use a new name:

"""Module to create a version of list that is more chainable"""

class chainable_list(list):
    """Same as list but sort() can now be chained"""
    def chainsort(this, *args, **kwargs):
        this.sort(*args, **kwargs)
        return this

Here it is on a list of ints:

>>> testink = chainable_list([3,5,1,7])
>>> testink
[3, 5, 1, 7]
>>> testink.chainsort()
[1, 3, 5, 7]
>>> testink.chainsort(reverse=True)
[7, 5, 3, 1]

Here it is on a list of strings that sort differently unless coerced back
into an int to show keyword arguments are passed:

>>> testink = chainable_list(["3","15","1","7"])
>>> testink.chainsort()
['1', '15', '3', '7']
>>> testink.chainsort(reverse=True)
['7', '3', '15', '1']
>>> testink.chainsort(key=int,reverse=True)
['15', '7', '3', '1']

I then tested the second method using the same name but asking the original
list sort to do things:

"""Module to create a version of list that is more chainable"""

class chainable_list(list):
    """Same as list but sort() can now be chained"""
    def sort(this, *args, **kwargs):
        list.sort(this, *args, **kwargs)
        return this

>>> testink = chainable_list(["3","15","1","7"])
>>> testink.sort()
['1', '15', '3', '7']
>>> testink.sort().sort(reverse=true)
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    testink.sort().sort(reverse=true)
NameError: name 'true' is not defined
>>> testink.sort().sort(reverse=True)
['7', '3', '15', '1']
>>> testink.sort().sort(reverse=True).sort(key=int)
['1', '3', '7', '15']

Again, it works fine. So if someone did something similar to many of the
methods that now return None, you could use the new class when needed.

This seems too simple so it must have been done. Obviously not in the
standard distribution but perhaps elsewhere. And, no, I do not expect a
method like pop() to suddenly return the list with a member dropped but it
would be nice to fix some like this one:

>>> testink.remove('7')
>>> testink
['1', '3', '15']

Meanwhile, I hear Beethoven is decomp..., well never mind! It was probably
Liszt!

-----Original Message-----
From: Tutor <tutor-bounces+avigross=verizon.net at python.org> On Behalf Of
Alan Gauld via Tutor
Sent: Tuesday, December 25, 2018 8:06 PM
To: tutor at python.org
Subject: Re: [Tutor] decomposing a problem

On 26/12/2018 00:00, Avi Gross wrote:

> great. Many things in python can be made to fit and some need work. 
> Dumb example is that sorting something internally returns None and not 
> the object itself.

This is one of my few complaints about Python.
In Smalltalk the default return value from any method is self. In Python it
is None.

self allows chaining of methods, None does not.
Introducing features like reversed() and sorted() partially addresses the
issue but leads to inconsistent and ugly syntax.

Smalltalk uses this technique so much it has its own code layout idiom
(Pythonised as
follows):

object
   .method1()
   .method2()
   .method3()
   ....
   .lastone()

We can do this with some methods but not all.
And of course methods that return a different type of value require careful
handling (eg. an
index() call in the middle of a set of list operations means the subsequent
methods are being called on an int not a list - which if handled correctly
can be confusing and if not handled correctly produces errors! (The
idiomatic way says don't chain with methods not returning self!)

In practice I (and the Smalltalk community) don't find that an issue in real
world usage, but it may have been why Guido chose not to do it that way.
But I still curse the decision every time I hit it!

But as I said, it's about the only thing in Python I dislike... a small
price to pay.

--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


_______________________________________________
Tutor maillist  -  Tutor at python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor



More information about the Tutor mailing list