Skip to content

Use itertools.pairwise instead of zipping a sequence against itself #3297

@Jeremiah-England

Description

@Jeremiah-England

Tonight I discovered itertools.pairwise (new in 3.10) and replaced 6 lines like this in a ~10,000 line codebase:

# Before:
for first, second in zip(my_sequence, my_sequence[1:], strict=False):
    ...

# After:
for first, second in pairwise(my_sequence):
    ...

I have no idea how easy this would be. But if it is easy it might make a nice rule!

And in addition to being less verbose, pairwise is also faster on my machine.

import timeit
from itertools import pairwise

short = [0] * 10
medium = [0] * 1_000
long = [0] * 1_000_000

print(timeit.timeit("list(pairwise(short))", globals=globals()))
print(timeit.timeit("list(zip(short, short[1:], strict=False))", globals=globals()))
# 0.5838822979985707
# 1.1156816439997783

print(timeit.timeit("list(pairwise(medium))", globals=globals(), number=10_000))
print(timeit.timeit("list(zip(medium, medium[1:], strict=False))", globals=globals(), number=10_000))
# 0.36417481299940846
# 0.4547197800002323

print(timeit.timeit("list(pairwise(long))", globals=globals(), number=10))
print(timeit.timeit("list(zip(long, long[1:], strict=False))", globals=globals(), number=10))
# 1.0911181840001518
# 1.499006936999649

Another common idiom for this uses indexes. But my gut tells me linting this would be much more difficult and error prone.

for i in range(len(my_sequence) - 2):
    first, second = my_sequence[i], my_sequence[i + 1]
    ...

Metadata

Metadata

Assignees

No one assigned

    Labels

    ruleImplementing or modifying a lint rule

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions