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

Nick Coghlan ncoghlan at gmail.com
Thu Oct 13 13:50:13 CEST 2011


On Thu, Oct 13, 2011 at 7:10 PM, Paul Moore <p.f.moore at gmail.com> wrote:
> 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'm much happier with the keyword - "postdef" provides a strong hint
to what it does, and also ties it in with the following function
definition.

>> 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.

It doesn't make a huge difference, as 'postdef' also works
sufficiently well as the keyword for classes as well (since the class
statement if more commonly known as a class definition).

Including classes may nudge the forward reference syntax back towards
the semantically neutral '@', though. The alternative would be to use
'def' for functions and 'class' for classes, which would be a little
ugly.

>> 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).

With an explicit keyword, mixing them may be OK, though. For decorator
factories, the explicit calling syntax is a little clumsy.

>> 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.

It's easier to see with syntax highlighting, but yeah, I'm not as sold
on the idea of using def for forward reference rather than '@' as I am
on the switch from a bare colon to the postdef keyword.

>> 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.

It's actually more that I wasn't entirely comfortable with suppressing
the name binding in the first place and changing to a keyword really
emphasised the "do the function definition as normal, but then run
this extra piece of code afterwards" aspect.

Exposing the function names by default can also help with testability
of code that overuses the new construct.

> - 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"?).

No, I think we want a symbol or a real keyword here. Getting too cute
with names may actually make it harder to implement and understand
rather than easier.

> - 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...

The leading colon to introduce the new clause was definitely far too
cryptic, so I'm a lot happier with the explicit 'postdef' keyword
idea. For the rest, I think it falls into the same category as lambda
abuse - overusing the post definition clause would be a code smell, to
be fought by the forces of style guides, code reviews and an emphasis
on writing testable code.

Cheers,
Nick.

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



More information about the Python-ideas mailing list