Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
flake8-comprehensions
Advanced tools
A flake8 plugin to help you write better list/set/dict comprehensions.
.. image:: https://img.shields.io/github/actions/workflow/status/adamchainz/flake8-comprehensions/main.yml.svg?branch=main&style=for-the-badge :target: https://github.com/adamchainz/flake8-comprehensions/actions?workflow=CI
.. image:: https://img.shields.io/pypi/v/flake8-comprehensions.svg?style=for-the-badge :target: https://pypi.org/project/flake8-comprehensions/
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge :target: https://github.com/psf/black
.. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=for-the-badge :target: https://github.com/pre-commit/pre-commit :alt: pre-commit
A flake8 <https://flake8.readthedocs.io/en/latest/>
_ plugin that helps you write better list/set/dict comprehensions.
Linting a Django project?
Check out my book Boost Your Django DX <https://adamchainz.gumroad.com/l/byddx>
__ which covers Flake8 and many other code quality tools.
Python 3.9 to 3.13 supported.
First, install with pip
:
.. code-block:: sh
python -m pip install flake8-comprehensions
Second, if you define Flake8’s select
setting, add the C4
prefix to it.
Otherwise, the plugin should be active by default.
<list/set/dict>
comprehension.Rules:
It's unnecessary to use list
, set
, or dict
around a generator expression, since there are equivalent comprehensions for these types.
For example:
list(f(x) for x in foo)
as [f(x) for x in foo]
set(f(x) for x in foo)
as {f(x) for x in foo}
dict((x, f(x)) for x in foo)
as {x: f(x) for x in foo}
<set/dict>
comprehension.Rules:
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:
set([f(x) for x in foo])
as {f(x) for x in foo}
dict([(x, f(x)) for x in foo])
as {x: f(x) for x in foo}
<list/tuple>
literal - rewrite as a <set/dict>
literal.<list/tuple>
literal - rewrite as a set literal.<list/tuple>
literal - rewrite as a dict literal.It's unnecessary to use a list or tuple literal within a call to set
or dict
.
For example:
set([1, 2])
as {1, 2}
set((1, 2))
as {1, 2}
set([])
as set()
dict([(1, 2)])
as {1: 2}
dict(((1, 2),))
as {1: 2}
dict([])
as {}
<dict/list>
comprehension - <builtin>
can take a generatorThis rule was dropped in version 3.4.0, because it promoted an increase in laziness which could lead to bugs.
<dict/list/tuple>
call - rewrite as a literal.It's slower to call e.g. dict()
than using the empty literal, because the name dict
must be looked up in the global scope in case it has been rebound.
Same for the other two basic types here.
For example:
dict()
as {}
dict(a=1, b=2)
as {"a": 1, "b": 2}
list()
as []
tuple()
as ()
<list/tuple>
passed to <list/tuple>
() - <advice>
.Rules:
<list/tuple>
passed to tuple() - <advice>
.<advice>
.Where <advice>
is either:
<list/tuple>
()<list/tuple>
literalIt's unnecessary to use a list or tuple literal within a call to list
or tuple
, since there is literal syntax for these types.
For example:
tuple([1, 2])
as (1, 2)
tuple((1, 2))
as (1, 2)
tuple([])
as ()
list([1, 2])
as [1, 2]
list((1, 2))
as [1, 2]
list([])
as []
It's unnecessary to use a list
around a list comprehension, since it is equivalent without it.
For example:
list([f(x) for x in foo])
as [f(x) for x in foo]
<dict/list/set>
comprehension - 'in' can take a generator.This rule was dropped in version 3.4.0, because it promoted an increase in laziness which could lead to bugs.
<list/reversed>
call around sorted().It's unnecessary to use list()
around sorted()
as it already returns a list.
It is also unnecessary to use reversed()
around sorted()
as the latter has a reverse
argument.
For example:
list(sorted([2, 3, 1]))
as sorted([2, 3, 1])
reversed(sorted([2, 3, 1]))
as sorted([2, 3, 1], reverse=True)
reversed(sorted([2, 3, 1], reverse=True))
as sorted([2, 3, 1])
<list/reversed/set/sorted/tuple>
call within <list/set/sorted/tuple>
().It's unnecessary to double-cast or double-process iterables by wrapping the listed functions within list
/set
/sorted
/tuple
.
For example:
list(list(iterable))
as list(iterable)
list(tuple(iterable))
as list(iterable)
tuple(list(iterable))
as tuple(iterable)
tuple(tuple(iterable))
as tuple(iterable)
set(set(iterable))
as set(iterable)
set(list(iterable))
as set(iterable)
set(tuple(iterable))
as set(iterable)
set(sorted(iterable))
as set(iterable)
set(reversed(iterable))
as set(iterable)
sorted(list(iterable))
as sorted(iterable)
sorted(tuple(iterable))
as sorted(iterable)
sorted(sorted(iterable))
as sorted(iterable)
sorted(reversed(iterable))
as sorted(iterable)
<reversed/set/sorted>
().It's unnecessary to reverse the order of an iterable when passing it into one of the listed functions will change the order again. For example:
set(iterable[::-1])
as set(iterable)
sorted(iterable)[::-1]
as sorted(iterable, reverse=True)
reversed(iterable[::-1])
as iterable
<dict/list/set>
comprehension - rewrite using <dict/list/set>
().It's unnecessary to use a dict/list/set comprehension to build a data structure if the elements are unchanged.
Wrap the iterable with dict()
, list()
, or set()
instead.
For example:
{a: b for a, b in iterable}
as dict(iterable)
[x for x in iterable]
as list(iterable)
{x for x in iterable}
as set(iterable)
map
usage - rewrite using a generator expression/<list/set/dict>
comprehension.map(func, iterable)
has great performance when func
is a built-in function, and it makes sense if your function already has a name.
But if your func is a lambda
, it’s faster to use a generator expression or a comprehension, as it avoids the function call overhead.
For example:
map(lambda x: x + 1, iterable)
to (x + 1 for x in iterable)
map(lambda item: get_id(item), items)
to (get_id(item) for item in items)
list(map(lambda num: num * 2, nums))
to [num * 2 for num in nums]
set(map(lambda num: num % 2 == 0, nums))
to {num % 2 == 0 for num in nums}
dict(map(lambda v: (v, v ** 2), values))
to {v : v ** 2 for v in values}
<dict/dict comprehension>
passed to dict() - remove the outer call to dict()It's unnecessary to use a dict
around a dict literal or dict comprehension, since either syntax already constructs a dict.
For example:
dict({})
as {}
dict({"a": 1})
as {"a": 1}
<any/all>
() prevents short-circuiting - rewrite as a generator.Using a list comprehension inside a call to any()
/all()
prevents short-circuiting when a True
/ False
value is found.
The whole list will be constructed before calling any()
/all()
, potentially wasting work.part-way.
Rewrite to use a generator expression, which can stop part way.
For example:
all([condition(x) for x in iterable])
as all(condition(x) for x in iterable)
any([condition(x) for x in iterable])
as any(condition(x) for x in iterable)
It's unnecessary to use a dict comprehension to build a dict with all values set to the same constant.
Use dict.fromkeys()
instead, which is faster.
For example:
{x: 1 for x in iterable}
as dict.fromkeys(iterable, 1)
{x: None for x in iterable}
as dict.fromkeys(iterable)
FAQs
A flake8 plugin to help you write better list/set/dict comprehensions.
We found that flake8-comprehensions demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.