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

Paul Moore p.f.moore at gmail.com
Thu Oct 13 11:10:08 CEST 2011


On 13 October 2011 09:14, Nick Coghlan <ncoghlan at gmail.com> wrote:
> That's basically why I went with the leading ':' - it's jarring enough
> to get your attention, without being so ugly as to be intolerable.
> However, Georg's "this doesn't look like Python any more" criticism
> has serious merit - while style guidelines can mitigate that to some
> degree (just as they advise against gratuitous use of lambda
> expressions when a named function would be better), there's an
> inherent ugliness to the syntax in the first draft of the PEP that may
> make it irredeemable.

Personally, I find the leading ":" too light (to my ageing eyes :-))
so that it gets lost. Also, I am now trained by decorators to see
lines starting with @ as "attached" to the following definition, in a
way that other syntax isn't.

As an alternative bikeshed colour, would @: work rather than plain @?


> I already think there are two simplifying assumptions that should be
> made at least for the first iteration of the idea:
>
> 1. Leave classes out of it, at least for now. We did that with
> decorators, and I think it's a reasonable approach to follow.

While I don't disagree per se, I suspect that statement-local classes
will be on the enhancement list from day 1 - the trick of using a
class as a local namespace is just too compelling. So deferring that
option may be a false economy.

> 2. The initial version should be an alternative to decorator syntax,
> not an addition to it. That is, you wouldn't be able to mix the first
> incarnation of a block prefix with ordinary decorators.

Agreed, and with this one I'm not sure it shouldn't stay a limitation
forever. Mixing the two seems like a step too far. (And if you really
need it, just call the decorator directly as part of the @:
statement).

> If we can find an approach that works for the basic case (i.e. naked
> function definition) and doesn't make people recoil in horror (esp.
> Guido), then we can look at expanding back to cover these two cases.
>
> I'll note that the only further syntax idea I've had is to replace the
> ':' with 'postdef' and the '@' with 'def', so some of the examples
> kicking around would become:
>
>    postdef x = weakref.ref(obj, def)
>    def report_destruction(obj):
>        print("{} is being destroyed".format(obj))
>
>    postdef funcs = [def(i) for i in range(10)]
>    def make_incrementor(i):
>        postdef return def
>        def incrementor(x):
>            return x + i
>
>    postdef sorted_list = sorted(original, key=def)
>    def normalise(item):
>        …
>
> That actually looks quite readable to me, and is fairly explicit about
> what it does: here's a piece of code to run after the following
> function has been defined. I definitely like it better than what I
> have in the PEP.

My instinct still prefers a form including a leading @, but I
definitely like this better than the bare colon. And given that the "@
attaches to the next statement" instinct is learned behaviour, I'm
sure I could learn to recognise something like this just as easily. I
*don't* like using def to mark the placeholder, though - too easily
lost.

> With this variant, I would suggest that any postdef clause be executed
> *in addition* to the normal name binding. Colliding on dummy names
> like "func" would then be like colliding on loop variables like "i" -
> typically harmless, because you don't use the names outside the
> constructs that define them anyway.

I'm not sure why you feel that using a keyword implies that the
binding behaviour should change - but as you say typically it's not
likely to matter.

Some other minor comments:

- I am +1 on this idea, but don't really have any particular use cases
so that's on a purely theoretical basis.
- The parallel with decorators makes this much easier to integrate
mentally than PEP 3150.
- Using _ as a throwaway name seems fine to me, and means there's
little need to worry about allowing the name to be omitted (although I
do think the unused name-as-documentation-only is a little jarring)
- The @ as reference to the local function is mildly ugly, in a way
that @ at the start of a line isn't. But I don't have any really good
alternatives to offer (other than maybe a special name with double
underscores, such as __this__, but I'm not convinced by that - hmm,
what about a bare double underscore, __? Too "cute"?).
- Georg's point about this not looking like Python any more is good. I
don't completely agree, and in particular I think that the semantics
are sufficiently Pythonic, it's just the syntax that is jarring, but
it *is* something to be careful of. Decorators felt much the same when
they were introduced, though...

Paul.



More information about the Python-ideas mailing list