[Python-Dev] Seeming unintended difference between list comprehensions and generator expressions...

Nick Coghlan ncoghlan at gmail.com
Sat Feb 21 01:35:20 CET 2009


Josiah Carlson wrote:
>> Similarly, a 3.x list comprehension [i*i for i in x] is very roughly
>> translated as:
>>
>>  def _lc(arg):
>>    result = []
>>    for i in arg:
>>      result.append(i*i)
>>    return result
>>
>>  <expr_value> = _lc(x)
> 
> I was under the impression that in 3.x, it was equivalent to
> list(<genexp>) .  Which would explain the difference between 2.6 and
> 3.0.

Semantically, the two translations end up being the same. Actually
*implementing* it that way turned out to be unnecessarily slow: the
comprehensions instead create a normal function that builds the desired
type of object (list/set/dict) incrementally rather than building a
generator function and invoking it. The speed increase comes from being
able to skip the generator resume/yield overhead on each iteration.

>> Like any function scope inside a class namespace, the body of a genexp
>> (and, in 3.x, comprehension) doesn't have direct access to the class
>> namespace because classes don't play any part in the lexical scoping rules.
> 
> Indeed, though I had thought (if only briefly ;) ) that when executing
> non-definitions in the class body, it would behave similar to the a
> more or less equivalent function-based class factory

I think there may be a section of the language reference that describes
it in those terms. If there is, it should probably be changed, since it
gives misleading ideas about how the scoping works. Execution of a class
body is actually a bit more like using an exec statement than it is like
an implicit function definition.

Cheers,
Nick.

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


More information about the Python-Dev mailing list