List Magic

Head, Tail

Altes Problem, geht man zumeist so an:

>>> l = list(range(10)) >>> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> head, tail = l[0], l[1:] >>> head 0 >>> tail [1, 2, 3, 4, 5, 6, 7, 8, 9]

Nach PEP 3132 wird das alles viel eleganter:

>>> head, *tail = list(range(10)) >>> head 0 >>> tail [1, 2, 3, 4, 5, 6, 7, 8, 9]

Was noch so geht

Zum Beispiel beim Iterieren über eine Liste von Tupeln das letzte Element extra behandeln:

>>> l = list((x, x+x, x*x) for x in range(5)) >>> l [(0, 0, 0), (1, 2, 1), (2, 4, 4), (3, 6, 9), (4, 8, 16)] >>> for *head, last in l: ... print(last, '->', head) ... 0 -> [0, 0] 1 -> [1, 2] 4 -> [2, 4] 9 -> [3, 6] 16 -> [4, 8]

Flatten

Verschachtelte Listen lassen sich durch eine List-Comprehension auflösen:

>>> ll = [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]] >>> [fl for at in ll for fl in at] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Das ganze ist aber nicht Speichereffizient. Wenn man über die Elemente in den Listen der Liste iterieren muss, greift man auf die itertools zurück:

>>> from itertools import chain >>> ll = [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]] >>> cl = chain.from_iterable(ll) >>> cl <itertools.chain object at 0x10a8b5b00> >>> for c in cl: ... print(c) ... 0 1 2 [...]

Achtung. Es handelt sich hier um einen Iterator. Wenn versucht wird mehrmals darüber zu iterieren, wird das nichts.

>>> ll = [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]] >>> cl = chain.from_iterable(ll) >>> list(cl) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(cl) []

Verschachtelt iterieren

Das ganze lässt sich aber auch dazu nutzen, mehrere for-loops abzukürzen:

>>> res = [] >>> for x in [0, 1, 2, 3, 4]: ... for y in [5, 6, 7, 8, 9]: ... res.append((x, y, x+y, x*y)) >>> res [(0, 5, 5, 0), (0, 6, 6, 0), (0, 7, 7, 0), ...]

… wird somit zu:

>>> nres = [(x, y, x+y, x*y) for x in [0, 1, 2, 3, 4] for y in [5, 6, 7, 8, 9]] >>> nres [(0, 5, 5, 0), (0, 6, 6, 0), (0, 7, 7, 0), ...] >>> assert res == nres
last update: 2024-01-28 12:40:56 +0100