List comprehension vs filter()

Peter Otten __peter__ at web.de
Wed Apr 20 12:41:18 CEST 2011


Chris Angelico wrote:

> Context: Embedded Python interpreter, version 2.6.6
> 
> I have a list of dictionaries, where each dictionary has a "type"
> element which is a string. I want to reduce the list to just the
> dictionaries which have the same "type" as the first one.
> 
> lst=[{"type":"calc",...},{"type":"fixed",...},{"type":"calc",...},...]
> 
> I'm seeing a weird difference between two otherwise-equivalent-looking
> ways of doing the job.
> 
> type=lst[0]["type"].lower()
> 
> lst=filter(lambda x: x["type"].lower()==type,lst) # Restrict to that one
> type
> 
> lst=[i for i in lst if i["type"].lower()==type] # Restrict to that one
> type
> 
> If I use the filter() method, the resulting list is completely empty.
> If I use the list comprehension, it works perfectly. Oddly, either
> version works in the stand-alone interpreter.
> 
> I have no idea where to start looking for the problem. Hints, please!
> 
> Chris Angelico

The assignment writes to the local namespace, the lambda function reads from 
the global namespace; this will only work as expected if the two namespaces 
are the same:

>>> exec """type = 42; print filter(lambda x: x == type, [42])""" in {}, {}
[]
>>> ns = {}
>>> exec """type = 42; print filter(lambda x: x == type, [42])""" in ns
[42]

The list comprehension doesn't introduce another namespace, at least in 2.x:

$ python2.7 -c 'exec("type = 42; print([x for x in [42] if x == type])", {}, 
{})'
[42]
$ python3.2 -c 'exec("type = 42; print([x for x in [42] if x == type])", {}, 
{})'
[]




More information about the Python-list mailing list