A flake8 plugin that helps you write better list/set/dict comprehensions.
Install from pip
with:
python -m pip install flake8-comprehensions
Python 3.5 to 3.8 supported.
When installed it will automatically be run as part of flake8
; you can check it is being picked up with:
$ flake8 --version
3.7.8 (flake8-comprehensions: 3.0.0, mccabe: 0.6.1, pycodestyle: 2.5.0, pyflakes: 2.1.1) CPython 3.8.0 on Linux
Code | Rule |
---|---|
C400 | Unnecessary generator - rewrite as a list comprehension. |
C401 | Unnecessary generator - rewrite as a set comprehension. |
C402 | Unnecessary generator - rewrite as a dict comprehension. |
C403 | Unnecessary list comprehension - rewrite as a set comprehension. |
C404 | Unnecessary list comprehension - rewrite as a dict comprehension. |
C405 | Unnecessary (list/tuple) literal - rewrite as a set literal. |
C406 | Unnecessary (list/tuple) literal - rewrite as a dict literal. |
C407 | Unnecessary (dict/list) comprehension - '<builtin>' can take a generator. |
C408 | Unnecessary (dict/list/tuple) call - rewrite as a literal. |
C409 | Unnecessary (list/tuple) passed to tuple() - (remove the outer call to tuple()/rewrite as a tuple literal). |
C410 | Unnecessary (list/tuple) passed to list() - (remove the outer call to list()/rewrite as a list literal). |
C411 | Unnecessary list call - remove the outer call to list(). |
C412 | Unnecessary (dict/list/set) comprehension - 'in' can take a generator. |
C413 | Unnecessary list call around sorted(). |
C413 | Unnecessary reversed call around sorted() - (use sorted(..., reverse=(True/False))/toggle reverse argument to sorted()). |
C414 | Unnecessary (list/reversed/set/sorted/tuple) call within list/set/sorted/tuple(). |
C415 | Unnecessary subscript reversal of iterable within reversed/set/sorted(). |
C416 | Unnecessary (list/set) comprehension - rewrite using list/set(). |
It's unnecessary to use list
, set
, or dict
around a generator expression, since there are equivalent comprehensions for these types. For example:
- Rewrite
list(f(x) for x in foo)
as[f(x) for x in foo]
- Rewrite
set(f(x) for x in foo)
as{f(x) for x in foo}
- Rewrite
dict((x, f(x)) for x in foo)
as{x: f(x) for x in foo}
It's unnecessary to use a list comprehension inside a call to set
or dict
, since there are equivalent comprehensions for these types. For example:
- Rewrite
set([f(x) for x in foo])
as{f(x) for x in foo}
- Rewrite
dict([(x, f(x)) for x in foo])
as{x: f(x) for x in foo}
It's unnecessary to use a list or tuple literal within a call to tuple
, list
, set
, or dict
since there is literal syntax for these types. For example:
- Rewrite
tuple([1, 2])
ortuple((1, 2))
as(1, 2)
- Rewrite
tuple([])
as()
- Rewrite
list([1, 2])
orlist((1, 2))
as[1, 2]
- Rewrite
list([])
as[]
- Rewrite
set([1, 2])
orset((1, 2))
as{1, 2}
- Rewrite
set([])
asset()
- Rewrite
dict([(1, 2)])
ordict(((1, 2),))
as{1: 2}
- Rewrite
dict([])
as{}
It's unnecessary to pass a list comprehension to some builtins that can take generators instead. For example:
- Rewrite
sum([x ** 2 for x in range(10)])
assum(x ** 2 for x in range(10))
- Rewrite
all([foo.bar for foo in foos])
asall(foo.bar for foo in foos)
- Rewrite
filter(lambda x: x % 2 == 0, [x ** 3 for x in range(10)])
asfilter(lambda x: x % 2 == 0, (x ** 3 for x in range(10)))
The list of builtins that are checked for are:
all
any
enumerate
filter
frozenset
map
max
min
sorted
sum
tuple
It's slower to call these types than to construct them with literals, e.g. dict()
is slower than {}
, because the name dict
must be looked up in the global scope in case it has been rebound, and it includes the overhead of a function call. Same for the other two builtin types here. For example:
- Rewrite
dict()
as{}
- Rewrite
list()
as[]
- Rewrite
tuple()
as()
It's unnecessary to use a list
around list comprehension, since it is equivalent without it. For example:
- Rewrite
list([f(x) for x in foo])
as[f(x) for x in foo]
It's unnecessary to pass a dict/list/set comprehension to 'in' that can take a generator instead. For example:
- Rewrite
y in [f(x) for x in foo]
asy in (f(x) for x in foo)
- Rewrite
y in {x ** 2 for x in foo}
asy in (x ** 2 for x in foo)
It's unnecessary to use list()
around sorted()
as it already returns a list. It is also suboptimal to use reversed()
around sorted()
as the latter has a reverse
argument. For example:
- Rewrite
list(sorted([2, 3, 1]))
assorted([2, 3, 1])
- Rewrite
reversed(sorted([2, 3, 1]))
assorted([2, 3, 1], reverse=True)
- Rewrite
reversed(sorted([2, 3, 1], reverse=True))
assorted([2, 3, 1])
It's unnecessary to change the type of the iterable or change the order of elements within certain other function calls that will themselves define the order of the iterable or the type that is output. For example:
- Rewrite
list(list(iterable))
aslist(iterable)
- Rewrite
list(tuple(iterable))
aslist(iterable)
- Rewrite
tuple(list(iterable))
astuple(iterable)
- Rewrite
tuple(tuple(iterable))
astuple(iterable)
- Rewrite
set(set(iterable))
asset(iterable)
- Rewrite
set(list(iterable))
asset(iterable)
- Rewrite
set(tuple(iterable))
asset(iterable)
- Rewrite
set(sorted(iterable))
asset(iterable)
- Rewrite
set(reversed(iterable))
asset(iterable)
- Rewrite
sorted(list(iterable))
assorted(iterable)
- Rewrite
sorted(tuple(iterable))
assorted(iterable)
- Rewrite
sorted(sorted(iterable))
assorted(iterable)
- Rewrite
sorted(reversed(iterable))
assorted(iterable)
It's unnecessary to reverse the order of an iterable using a [::-1]
before passing it into set()
which will randomize the order, sorted()
which will return a new sorted list, or reversed()
which will effectively return the original iterable. For example:
- Rewrite
set(iterable[::-1])
asset(iterable)
- Rewrite
sorted(iterable[::-1])
assorted(iterable, reverse=True)
- Rewrite
reversed(iterable[::-1])
asiterable
It's unnecessary to use a list comprehension if the elements are unchanged. The iterable should be wrapped in list()
or set()
instead. For example:
- Rewrite
[x for x in iterable]
aslist(iterable)
- Rewrite
{x for x in iterable}
asset(iterable)