Tipps and Tricks ---------------- Sometimes it is not hard to speed up some simple tasks. This page shows some templates that might help to improve the performance of your code. .. note:: This page is more or less a stub right now. If you have any interesting facts to share please open a Pull Request or Issue. Map ^^^ :py:func:`map` can be much faster than list comprehensions or generator expressions *if and only if* the `function` is implemented in C without Python attribute lookup. All Python built-ins are written in C and some (there are exceptions like :py:func:`abs`) that perform really fast with :py:func:`map`: .. code:: python >>> import random >>> l1 = [random.randint(0, 1000) for _ in range(20000)] >>> l2 = [random.randint(0, 1000) for _ in range(20000)] >>> l3 = [random.randint(0, 1000) for _ in range(20000)] >>> %timeit [min(i) for i in zip(l1, l2, l3)] # doctest: +SKIP 100 loops, best of 3: 4.94 ms per loop >>> %timeit list(map(min, l1, l2, l3)) # doctest: +SKIP 100 loops, best of 3: 3.24 ms per loop Sometimes it is not possible to use such a function directly with :py:func:`map` but before you use :py:func:`functools.partial` you can always use :py:func:`itertools.repeat`! .. code:: python >>> from itertools import repeat >>> lst = [0]*100000 >>> %timeit [isinstance(i, int) for i in lst] # doctest: +SKIP 100 loops, best of 3: 17.4 ms per loop >>> %timeit list(map(isinstance, lst, repeat(int))) # doctest: +SKIP 100 loops, best of 3: 7.99 ms per loop .. note:: Using :py:func:`itertools.repeat` is only faster for very **few** functions. :py:func:`isinstance` is one of those! Predicate functions ^^^^^^^^^^^^^^^^^^^ Sometimes one needs a predicate function or filter out some items. One little (although sometimes impossible!) trick is to use methods as predicate: .. code:: python >>> import random >>> from iteration_utilities import consume >>> lst = [random.random() for _ in range(200000)] >>> %timeit consume((i for i in lst if i > 0.5), None) # doctest: +SKIP 100 loops, best of 3: 9.51 ms per loop >>> %timeit consume(filter((0.5).__lt__, lst), None) # doctest: +SKIP 100 loops, best of 3: 8.03 ms per loop This shows only a slight improvement but it's not always possible to use a generator expression or list comprehension. If you do the same with :py:func:`operator.lt` and :py:func:`functools.partial` or with a custom function you'll see the performance increase: .. code:: python >>> from functools import partial >>> from operator import lt >>> partial_gt_05 = partial(lt, 0.5) >>> %timeit consume(filter(lambda x: x > 0.5, lst), None) # doctest: +SKIP 10 loops, best of 3: 22.3 ms per loop >>> %timeit consume(filter(partial_gt_05, lst), None) # doctest: +SKIP 100 loops, best of 3: 17 ms per loop .. warning:: Using the ``__lt__`` and equivalent methods is not always possible, for example this bypasses Pythons data model. For example the following will fail: ``(5).__lt__(10.2)`` because integer don't compare to floats. In that case you need to use: ``(5.0).__lt__(10.2)``. However public methods are always available as well as several special methods like: ``__len__``, ``__contains__``, ...