unnecessary-map (C417)
Added in v0.0.74 · Related issues · View source
Derived from the flake8-comprehensions linter.
Fix is sometimes available.
What it does
Checks for unnecessary map() calls with lambda functions.
Why is this bad?
Using map(func, iterable) when func is a lambda is slower than
using a generator expression or a comprehension, as the latter approach
avoids the function call overhead, in addition to being more readable.
This rule also applies to map() calls within list(), set(), and
dict() calls. For example:
- Instead of
list(map(lambda num: num * 2, nums)), use[num * 2 for num in nums]. - Instead of
set(map(lambda num: num % 2 == 0, nums)), use{num % 2 == 0 for num in nums}. - Instead of
dict(map(lambda v: (v, v ** 2), values)), use{v: v ** 2 for v in values}.
Example
Use instead:
Known problems
A map object and a generator expression are not interchangeable when the
mapped expression raises. Once an exception propagates out of a generator,
the generator is closed, so every later next() call raises
StopIteration. A map object is not closed, so iteration can resume after
the error:
values = ["0", "x", "2"]
m = map(lambda v: int(v), values)
next(m) # 0
next(m) # raises ValueError
next(m) # 2
g = (int(v) for v in values)
next(g) # 0
next(g) # raises ValueError
next(g) # raises StopIteration
Ruff cannot tell whether a caller relies on this difference, so the diagnostic is still reported in such cases.
Fix safety
This rule's fix is marked as unsafe because it can change how errors propagate out of the resulting iterator, as described above. It may also drop comments when rewriting the call.