LangWart: Method congestion from mutate multiplicty

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sat Feb 9 04:36:52 CET 2013


Rick Johnson wrote:

> The solution is simple. Do not offer the "copy-mutate" methods and force
> all mutation to happen in-place:
> 
> py> l = [1,2,3]
> py> l.reverse
> py> l
> [3,2,1]
> 
> If the user wants a "mutated copy" he should explicitly create a new
> object and then apply the correct mutator method:
> 
> py> a1 = [1,2,3]
> py> a2 = list(a1).reverse()


Oh wow, Rick has re-discovered programming in Python during the mid to late
1990s!

I was there, and I remember what it was like. For about a month, you try
hard to follow Rick's prescription. Then you realise that with a small
helper function, you can halve the amount of code it takes to do a common
operation:

def reversed(sequence):
    seq = list(sequence)
    seq.reverse()
    return seq


Soon you've copied this reversed() function into all your projects. And of
course, they start to diverge... in project A, you only care about lists.
In project B, you realise that you also need to support tuples and strings:


def reversed(sequence):
    seq = sequence[:]
    try:
        seq.reverse()
    except AttributeError:
        seq = seq[::-1]
    return seq

which in project C you realise can be shortened:

def reversed(sequence):
    return sequence[::-1]


until you get to project D when you realise that you also want this to work
on dicts:

def reversed(sequence):
    everything = list(sequence)
    return everything[::-1]


and then in project E you wonder why reversed(string) returns a list:

def reversed(sequence):
    everything = list(sequence)[::-1]
    if isinstance(sequence, tuple):
        return tuple(everything)
    elif isinstance(sequence, str):
        return ''.join(everything)
    return everything


and then finally you learn about iterators and generators and become more
comfortable with a flow-based programming paradigm and generators:

def reversed(sequence):
    for item in list(sequence)[::-1]:
        yield item

at which point you realise that, hell, this is so useful that pretty much
everyone has implemented it a dozen times or more in their own projects,
and you start to agitate for it to be added to the builtins so that there
is *one* implementation, done *right*, that everyone can use.

And then you get told that Guido's time machine has struck again, because
Python has already had this since Python 2.4.



-- 
Steven




More information about the Python-list mailing list