Lambdas

Lambdas sind anonyme Funktionen in Python.

Man kann folgende Funktion…

def dx(x, y):
    return (x, y, x+y, x*y)

auch kompakter hinschreiben:

lx = lambda x, y: (x, y, x+y, x*y)
>>> lx(0, 1); dx(0, 1)
(0, 1, 1, 0)
(0, 1, 1, 0)
>>> lx(1, 2); dx(1, 2)
(1, 2, 3, 2)
(1, 2, 3, 2)
>>> lx(2, 3); dx(2, 3)
(2, 3, 5, 6)
(2, 3, 5, 6)
>>> for n in range(1337+1):
...     assert lx(n, n+1) == dx(n, n+1)

Aber…

PEP 8#programming-recommendations ist da unmissverständlich:

Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier.

Also, wozu der ganze Aufwand?

Es gibt Funktionen, die als Parameter wiederum eine Funktion übergeben bekommen. Dies ist an manchen Stellen recht praktisch.

Zum Beispiel nuzen wir eine Klasse als Container, um Dinge darin zu speichern:

class C:
    def update(self, func, key):
        setattr(self, key, func(
            getattr(self, key, None)
        ))
>>> c = C()
>>> c.holy = 'hand grenade'
>>> c.num = 23
>>> vars(c)
{'holy': 'hand grenade', 'num': 23}

Die update-Funktion macht folgendes:

>>> c.update(str.upper, 'holy')
>>> vars(c)
{'holy': 'HAND GRENADE', 'num': 23}

Besteht nun Bedarf an spezielleren Operationen, kommt das lambda ins Spiel:

>>> c.update(lambda n: n*n, 'num')
>>> vars(c)
{'holy': 'HAND GRENADE', 'num': 529}

Vorsicht

Lambdas sind abhänig von ihrem jeweiligen Kontext:

>>> y = 23
>>> f = lambda x: x+y
>>> f(23)
46
>>> y = 42
>>> f(23)
65

Der Fix hierzu wäre es, das y in den Scope des lambdas beim Erstellen zu übernehmen:

>>> y = 23
>>> f = lambda x, y=y: x+y
>>> f(23)
46
>>> y = 42
>>> f(23)
46

Wie man sieht, dies alles führt zu unleserlichen Code, bis hin zu schweren Verletzungen beim Debuggen..