Ok, let's see some funny/useful Python code.

[Grouping by]

We have a list of elements and we want to group them by some property:

from pprint import pprint

def group_by(fnx, data):  
d = dict()  
for element in data:  
d.setdefault(fnx(element), []).append(element)  
return d  
order_by_lenght = lambda x: len(x)  
order_by_start_char = lambda x: x[:1]

Now we can thest our functions by doing:

>> numbers = ["one", "two", "three", "four", "five", "six", "sevent",
"eight", "nine", "ten"]  
>> pprint( group_by(order_by_lenght, numbers))  
{3: ['one', 'two', 'six', 'ten'],  
4: ['four', 'five', 'nine'],  
5: ['three', 'eight'],  
6: ['sevent']}

>> pprint( group_by(order_by_start_char, numbers))  
{'e': ['eight'],  
'f': ['four', 'five'],  
'n': ['nine'],  
'o': ['one'],  
's': ['six', 'sevent'],  
't': ['two', 'three', 'ten']}

[Infinite dictionary (defaultdict)]

Very useful data structure in some cases.

from collections import defaultdict  
new_dict = lambda: defaultdict(new_dict)  
d = defaultdict(new_dict)

d["foo"]["bar"] = "Ojete"  
d["foo"]["re"] = "Calor"  
d["bar"]["lala"] = "Picor"  
d["baz"]["bar"]["foo"] = "Lala"

>> print d["bar"].keys()

>> print d["bar"]["lala"]

>> print d["foo"].keys()

['re', 'bar']  
>> print d["foo"].items()

[('re', 'Calor'), ('bar', 'Ojete')]

[Problems with list comprehensions and the use of lambdas wrapping variables]

When we create a list of lambda functions, and this functions are wrapping a generated value in the list, we don't usually have the expected results:

>>> test1 = [ lambda: n for n in range(5) ]

>>> for fnx in test1:

>>>    print fnx()

4 4 4 4 4

Oooops. That's not what I expected. I expected something like "0 1 2 3 4". Jumm... Why this result then? The problem here is that the lambda is not wrapping a value, but a reference to "n". The "n" variable changes in every iteration of the list comprehension and the last value it has is a "4". That's why every time me call the lambda functions inside de list "test1" we have the same result: the references of "n" are pointing to the same variable. We can do two tests for proving that:

>>> test1 = [ lambda: n for n in range(5) ]

>>> print vars()["n"]


Ok, the variable "n" in this scoping is "4". The other test we can do is to change the value of the variable "n" and see what happens:

>>> test1 = [ lambda: n for n in range(5) ]

>>> n = "foo"

>>> for fnx in test1:

>>>    print fnx()

foo foo foo foo foo

And this is it. So, what solution we have for this problem? Use iterators.

>>> test2 = (lambda: n for n in range(5))

>>>for fnx2 in test2:  
>>> print fnx2(),  
0 1 2 3 4

This time the lambda is storing a reference to "n", but the as we are using a generator, the variable is just assigned when is requested (when the "for" executes a test2.next()).

And this is it.