Skip to content

SIM110: Recommend proper usage of all and any #16904

@davfsa

Description

@davfsa

Summary

The problem

all and any are great built-ins, but only when used correctly. They have common pitfalls that seriously hurts performance.

Taking for example, the following piece of code (this is not real code, it is just an example!):

for elm in lst:
    if elm > 0:
        return True
return False

ruff (if rule SIM110 is enabled) will suggest to turn it into:

return any(elm > 0 for elm in lst)

which uses a generator expression, which is wayy (2 y's) slower than the for loop it is replacing

Benchmark
lst = [0 for _ in range(10000)] + [1]

def for_list():
    for elm in lst:
        if elm > 0:
            return True
    return False

def any_gen():
    return any(elm > 0 for elm in lst)

def any_proper_gen():
    return any(True for elm in lst if elm > 0)

def any_list():
    return any([elm > 0 for elm in lst])
%timeit for_list()
113 μs ± 253 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

%timeit any_gen()
225 μs ± 1.67 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

%timeit any_proper_gen()
108 μs ± 182 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

%timeit any_list()
130 μs ± 531 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

You usually want lazy evaluation in these cases, which is why I included any_list to show that [] could be another option, but is usually unwanted)

Proposed solution

Instead of the original code, ruff should suggest:

return any(True for elm in lst if elm > 0)

This is a bit more unreadable, so it would maybe be paired with another performance rule (probably under PERF) to catch incorrect uses of any and all, as well as suggest the correct code for SIM110

References

I always assumed any and all were slower than a normal loop outright, until I started migrating one of my projects to use ruff, which lead me to actually research this and found these amazing answers on StackOverflow, which helped me greatly to write this issue

https://stackoverflow.com/a/44803103
https://stackoverflow.com/a/44813751

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationneeds-decisionAwaiting a decision from a maintainerruleImplementing 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