[Python-ideas] Statement local functions and classes (aka PEP 3150 is dead, say 'Hi!' to PEP 403)

Nick Coghlan ncoghlan at gmail.com
Fri Oct 14 05:20:13 CEST 2011

On Fri, Oct 14, 2011 at 11:10 AM, Ron Adam <ron3200 at gmail.com> wrote:
> Using your sort example.  Lets say we rewrite that concept so it's more
> general using a decorator that can be reused.  In this case, the key
> isn't the reusable part.  It's the part that changes when we do sorts,
> so it's the part we put the decorator on to create a new sorted
> variation.
> def sorted_with(key):
>    def _(seq):
>        return sorted(seq, key=key)
>    return _
> @sorted_with
> def key_sorted(item):
>   return item.attr1, item.attr2
> new_list = key_sorted(original_list)

Seriously? You're suggesting that mess of symbols and indentation as a
good answer to the programming task "I want to sort the items in this
sequence according to the values of attr1 and attr2"?

The closest Python currently comes to being able to express that
concept cleanly is either:

    sorted_list = sorted(original, key=(lambda v: v.attr1, v.attr2))


    sorted_list = sorted(original, key=operator.attrgetter('attr1', 'attr2'))

Both of those work, but neither of them reaches the bar of "executable
pseudocode" the language prides itself on.

PEP 403 also fails pretty abysmally (alas) on that front:

    postdef sorted_list = sorted(original, key=sort_key)
    def sort_key(item):
        return item.attr1, item.attr2

The named function version fails because it gets things out of order:

    def sort_key(item):
        return item.attr1, item.attr2

    sorted_list = sorted(original, key=sort_key)

That's more like pseudo code for "First, define a function that
returns an object's attr1 and attr2 values. Than use that function to
sort our list", a far cry from the originally requested operation.

PEP 3150, on the other hand, actually gets close to achieving the
pseudocode standard:

    sorted_list = sorted(original, key=sort_key) given:
        def sort_key(item):
            return item.attr1, item.attr2

"Sort the items in this sequence according to the supplied key
function. The key function returns the values of attr1 and attr2 for
each item."

> We can reuse the sorted_with decorator with as may key functions as we
> want.  That reuse is an important feature of decorators.

No, no, no - this focus on reusability is *exactly* the problem. It's
why callback programming in Python sucks - we force people to treat
one-shot functions as if they were reusable ones, *even when those
functions aren't going to be reused in any other statement*.

That's the key realisation that I finally came to in understanding the
appeal of multi-line lambdas (via Ruby's block syntax): functions
actually have two purposes in life. The first is the way they're
traditionally presented: as a way to structure algorithms into
reusable chunks, so you don't have to repeat yourself. However, the
second is to simply hand over a section of an algorithm to be executed
by someone else. You don't *care* about reusability in those cases -
you care about handing the code you're currently writing over to be
executed by some other piece of code. Python only offers robust syntax
for the first use case, which is always going to cause mental friction
when you're only interested in the latter aspect.

Interestingly, the main thing I'm getting out of this discussion is
more of an idea of why PEP 3150 has fascinated me for so long. I
expect the outcome is going to be that 403 gets withdrawn and 3150
resuscitated :)


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list