[Python-ideas] Assignments in list/generator expressions
Guido van Rossum
guido at python.org
Mon Apr 11 16:57:30 CEST 2011
On Sun, Apr 10, 2011 at 9:20 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On Mon, Apr 11, 2011 at 3:42 AM, Guido van Rossum <guido at python.org> wrote:
>> OTOH I am personally a big fan of PEP 3150; now that the moratorium is
>> lifted I hope that someone will attempt a proper implementation of it
>> so we can find out all the odd corner cases (which I'm sure will be
>> plentiful given that this is quite a novel thing for Python).
>
> Not *quite* as novel as one might first think - the specific proposal
> I currently have in there has its roots in the way list/set/dict
> comprehensions work under the hood (in CPython, anyway). So we know
> the core principle is sound, although I'm sure you're correct that
> there are more corner cases still to be found in generalising the
> comprehension-style copy-in/copy-out semantics appropriately.
>
> I also thought of a somewhat decent use case for the feature, too:
> "builder" code in module and class namespaces, where you need some
> temporary functions, variables and loops to create a named variable,
> but then have to make sure to clean up your temporary storage
> locations to avoid polluting the public namespace. In the past, I'd
> mostly been thinking in terms of function namespaces, and keeping
> those "clean" is nowhere near as important as the situation for
> classes and modules (it's quite likely someone else has brought this
> up in the past, .
>
> To lift some examples from
> https://bitbucket.org/pypy/pypy/src/default/lib_pypy/disassembler.py
> (which is what got me thinking along these lines)
>
> from opcode import __all__ as _opcodes_all
> __all__ = ["dis","disassemble","distb","disco"] + _opcodes_all
> del _opcodes_all
>
> Could become:
>
> __all__ = ["dis","disassemble","distb","disco"] + opcode.__all__ given:
> import opcode
I like this one, but I'd like to see some more local examples too.
> And:
>
> def _setup():
> for opcode in opname:
> if not opcode.startswith('<'):
> class O(Opcode):
> pass
> opcode = opcode.replace('+', '_')
> O.__name__ = opcode
> globals()[opcode] = O
>
> _setup()
>
> Could become:
>
> pass given: # I'll add "pass" to the list of supported statements in PEP 3150
> for opcode in opname:
> if not opcode.startswith('<'):
> class O(Opcode):
> pass
> opcode = opcode.replace('+', '_')
> O.__name__ = opcode
> globals()[opcode] = O
>
> There's also a performance hack in there: "given:" drops you down into
> a function scope, so you get the benefits of function local
> performance.
Can't say I like this one. "pass given" sounds icky (and I think
earlier in this thread someone flagged it as undesirable).
I think that "given" will particularly shine in code written in a
"top-down" programming style, where one first presents the high-level
outcome and pushes details to the back. This can currently be done
quite well by putting the "main()" function definition first and then
developing it from there, but there is a certain elegance in having
the helper functions not exposed at the module level. (Although I can
also see that people who really like this style will overuse it and
put everything in a big sprawling deeply-nested structure, as opposed
to making the helpers all siblings. And it won't increase
testability.)
--
--Guido van Rossum (python.org/~guido)
More information about the Python-ideas
mailing list