[Python-3000] List & set comprehensions patch
Georg Brandl
g.brandl at gmx.net
Tue Mar 6 18:38:27 CET 2007
Nick Coghlan schrieb:
> Georg and I have been working on the implementation of list
> comprehensions which don't leak their iteration variables, along with
> the implementation of set comprehensions. The latest patch can be found
> as SF patch #1660500 [1]. The file new-set-comps.diff is the combined
> patch which implements both features, and unifies handling of the
> different kinds of comprehension. In an effort to improve readability,
> the patch also converts the sets in symtable.c to be actual PySet
> objects, rather than PyDict objects with None keys and tries to reduce
> the number of different meanings assigned to the term 'scope'.
>
> One of the comments made on Georg's initial attempt at implementing
> these features was that it would be nice to avoid the function call
> overhead in the listcomp & setcomp case (as it appears at first glance
> that the internal scope can be temporary). I tried to do that and
> essentially failed outright - working through symtable.c and compile.c,
> I found that dealing with the scoping issues created by the possibility
> of nested genexps, lambdas and list or set comprehensions would pretty
> much require reimplementing all of the scoping rules that functions
> already provide.
I have to thank you for digging through all that code and cases, which I always
dreaded ;)
> There are also a couple of tests we had to disable - one in test_dis,
> one in test_grammar. Suggestions on how to reinstate those (or agreement
> that it is OK to get rid of them) would be appreciated.
The one in test_grammar is certainly okay, since it uses syntax which
was agreed upon to be invalid in Py3k.
> The PySet update code in symtable.c currently uses PyNumber_InplaceOr
> with a subsequent call to Py_DECREF to counter the implicit call to
> Py_INCREF. Should this be changed to use PyObject_CallMethod to invoke
> the Python level update method?
Why not add a C-level PySet_Update API?
> There are also two backwards compatibility problems which came up:
>
> - code which explicitly deleted the listcomp variable started
> throwing NameErrors. Several tweaks were needed in the standard library
> to fix this.
This may be hard to catch with the 2to3 tool, but perhaps a certain heuristics
(del statement after a statement involving a list comprehension) could apply.
Furthermore, I don't think that "trick" is mostly used on module-level to
avoid cluttering up the namespace, so a codebase which really uses its modules
should see early failures.
> - only the outermost iterator expression is evaluated in the scope
> containing the comprehension (just like generator expressions). This
> means that the inner expressions can no longer see class variables and
> values in explicit locals() dictionaries provided to exec & friends.
> This didn't actually cause any problems in the standard library - I only
> note it because my initial implementation mistakenly evaluated the
> outermost iterator in the new scope, which *did* cause severe problems
> along these lines.
It must be noted that this was always the case for generator expressions, so
if a LC should only be syntactic sugar for list(genexp) as written in the PEP,
this is even correct behavior.
cheers,
Georg
More information about the Python-3000
mailing list