[Python-ideas] Add "equal" builtin function

Paul Moore p.f.moore at gmail.com
Thu Oct 6 15:15:04 EDT 2016


On 6 October 2016 at 18:09, Filipp Bakanov <filipp at bakanov.su> wrote:
> Seems like itertools recipes already have "all_equal" function. What do you
> think about moving it from recipes to itertools? I suggest a C
> implementation with optimisations for builtin collections.

Interestingly, the recipe given there was not mentioned in the
stackoverflow thread. Testing it against Steven's example given above:

recipe.py:

from itertools import groupby

def all_equal_1(iterable):
    "Returns True if all the elements are equal to each other"
    g = groupby(iterable)
    return next(g, True) and not next(g, False)

def all_equal_2(iterable):
    it = iter(iterable)
    sentinel = object()
    first = next(it, sentinel)
    return all(x == first for x in it)

Results:

> # Itertools recipe, all different
>py -m perf timeit -s "from recipe import all_equal_1, all_equal_2; x = range(1000); y = [0] * 1000" "all_equal_1(x)"
....................
Median +- std dev: 596 ns +- 10 ns

> # Itertools recipe, all the same
>py -m perf timeit -s "from recipe import all_equal_1, all_equal_2; x = range(1000); y = [0] * 1000" "all_equal_1(y)"
....................
Median +- std dev: 7.17 us +- 0.05 us

> # Steven's recipe, all different
>py -m perf timeit -s "from recipe import all_equal_1, all_equal_2; x = range(1000); y = [0] * 1000" "all_equal_2(x)"
....................
Median +- std dev: 998 ns +- 12 ns

> # Steven's recipe, all the same
>py -m perf timeit -s "from recipe import all_equal_1, all_equal_2; x = range(1000); y = [0] * 1000" "all_equal_2(y)"
....................
Median +- std dev: 84.3 us +- 0.9 us

So the itertools recipe is just under twice as fast for all-different
values, and over 10 times faster if all the values are the same.

The moral here is probably to check the itertools recipes, they are
really well coded.

If you really feel that it's worth promoting this recipe to an actual
itertools function, you should probably create a tracker item for it,
aimed at Python 3.7, with a patch implementing it. My feeling is that
Raymond (who's in charge of the itertools module) won't think it's
worth including - he's typically very cautious about adding itertools
unless they have proven broad value. But that's just my guess, and the
only way to know for sure is to ask.

BTW, given that this *is* already an itertools recipe, it seems clear
to me that the only reasonable place to put it if it does go into core
Python would be the itertools module.

Paul


More information about the Python-ideas mailing list