python tip

Python unpacking tricks

Unpack variables from iterable.

# One can unpack all iterables (tuples, list etc)
>>> a, b, c = 1, 2, 3
>>> a, b, c
(1, 2, 3)

>>> a, b, c = [1, 2, 3]
>>> a, b, c
(1, 2, 3)

Swap variables values.

>>> a, b = 1, 2
>>> a, b = b, a
>>> a, b
(2, 1)

Unpack variables from iterable without indicating all elements.

>>> a, *b, c = [1, 2, 3, 4, 5]
>>> a
1
>>> b
[2, 3, 4]
>>> c
5

Unpack variables using the splat operator.

>>> def test(x, y, z):
>>>     print(x, y, z)  
>>> res = test(*[10, 20, 30]) 
10 20 30
>>> res = test(**{'x': 1, 'y': 2, 'z': 3} )
10 20 30  

Flatten iterables.

>>> a = [[1, 2], [3, 4], [5, 6]]
>>> list(itertools.chain.from_iterable(a))
[1, 2, 3, 4, 5, 6]

Creating cartesian products from iterables.

>>> for p in itertools.product([1, 2, 3], [4, 5]):
>>>    print(''.join(str(x) for x in p))

(1, 4)
(1, 5)
(2, 4)
(2, 5)
(3, 4)
(3, 5)

Creating permutation from iterable.

>>> for p in itertools.permutations([1, 2, 3, 4]):
>>>      print(''.join(str(x) for x in p))
123
132
213
231
312
321

Creating ngram from iterable.

>>> from itertools import islice
>>> def n_grams(a, n):
...     z = (islice(a, i, None) for i in range(n))
...     return zip(*z)
...
>>> a = [1, 2, 3, 4, 5, 6]
>>> n_grams(a, 3)
[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6)]
>>> n_grams(a, 2)
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
>>> n_grams(a, 4)
[(1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6)]

Combining two iterables of tuples with padding or pivot nested iterable with padding.

>>> import itertools as it
>>> x = [1, 2, 3, 4, 5]
>>> y = ['a', 'b', 'c']
>>> list(zip(x, y))
[(1, 'a'), (2, 'b'), (3, 'c')]

>>> list(it.zip_longest(x, y))
[(1, 'a'), (2, 'b'), (3, 'c'), (4, None), (5, None)]

Creating a combination of k things from an iterable of n

>>> import itertools
>>> bills = [20, 20, 20, 10, 10, 10, 10, 10, 5, 5, 1, 1, 1, 1, 1]
>>> list(itertools.combinations(bills, 3))
[(20, 20, 20), (20, 20, 10), (20, 20, 10), ... ]

Creating accumulated results of iterable given a function

>>> import itertools
>>> list(itertools.accumulate([9, 21, 17, 5, 11, 12, 2, 6], min))
[9, 9, 9, 5, 5, 5, 2, 2]

Creating an iterator that returns elements from the iterable as long as the predicate is true

>>> import itertools
>>> itertools.takewhile(lambda x: x < 3, [0, 1, 2, 3, 4])  
[0, 1, 2]

>>> it.dropwhile(lambda x: x < 3, [0, 1, 2, 3, 4])
[3, 4]

Creating an iterator that filters elements from iterable returning only those for which the predicate is False

>>> import itertools
# keeping only false values
>>> list(itertools.filterfalse(bool, [None, False, 1, 0, 10]))
[None, False, 0]

Creating an iterator that computes the function using arguments obtained from the iterable of iterables

>>> import itertools 
>>> import operator
>>> a = [(2, 6), (8, 4), (7, 3)]
>>> list(itertools.starmap(operator.mul, a))
[12, 32, 21]