Um plugin flake8 que ajuda você a escrever melhores compreensões de lista/conjunto/dict.
Lintando um projeto Django? Confira meu livro Boost Your Django DX que cobre Flake8 e muitas outras ferramentas de qualidade de código.
Suporte para Python 3.9 a 3.13.
Primeiro, instale com pip
:
python -m pip install flake8-comprehensions
Segundo, se você definir a configuração select
do Flake8, adicione o prefixo C4
a ela. Caso contrário, o plugin deverá estar ativo por padrão.
<list/set/dict>
.Regras:
É desnecessário usar list
, set
ou dict
em torno de uma expressão geradora, pois existem compreensões equivalentes para esses tipos. Por exemplo:
list(f(x) for x in foo)
como [f(x) for x in foo]
set(f(x) for x in foo)
como {f(x) for x in foo}
dict((x, f(x)) for x in foo)
como {x: f(x) for x in foo}
<set/dict>
.Regras:
É desnecessário usar uma compreensão de lista dentro de uma chamada para set
ou dict
, pois existem compreensões equivalentes para esses tipos. Por exemplo:
set([f(x) for x in foo])
como {f(x) for x in foo}
dict([(x, f(x)) for x in foo])
como {x: f(x) for x in foo}
<list/tuple>
desnecessário - reescreva como um literal <set/dict>
.<list/tuple>
desnecessário - reescrever como um conjunto literal.<list/tuple>
desnecessário - reescreva como um literal de ditado. Não é necessário usar uma lista ou tupla literal em uma chamada para set
ou dict
. Por exemplo:
set([1, 2])
como {1, 2}
set((1, 2))
como {1, 2}
set([])
como set()
dict([(1, 2)])
como {1: 2}
dict(((1, 2),))
como {1: 2}
dict([])
como {}
<dict/list>
- <builtin>
pode usar um geradorEsta regra foi abandonada na versão 3.4.0, pois promovia um aumento na preguiça que poderia gerar bugs.
<dict/list/tuple>
desnecessária - reescrita como literal. É mais lento chamar, por exemplo, dict()
do que usar o literal vazio, porque o nome dict
deve ser procurado no escopo global caso tenha sido recuperado. O mesmo para os outros dois tipos básicos aqui. Por exemplo:
dict()
como {}
dict(a=1, b=2)
como {"a": 1, "b": 2}
list()
como []
tuple()
como ()
<list/tuple>
desnecessário passado para <list/tuple>
() - <advice>
.Regras:
<list/tuple>
desnecessário passado para tuple() - <advice>
.<advice>
. Onde <advice>
está:
<list/tuple>
()<list/tuple>
É desnecessário usar uma lista ou tupla literal em uma chamada para list
ou tuple
, pois há sintaxe literal para esses tipos. Por exemplo:
tuple([1, 2])
como (1, 2)
tuple((1, 2))
como (1, 2)
tuple([])
como ()
list([1, 2])
como [1, 2]
list((1, 2))
como [1, 2]
list([])
como []
É desnecessário usar uma list
em torno de uma compreensão de lista, pois é equivalente sem ela. Por exemplo:
list([f(x) for x in foo])
como [f(x) for x in foo]
<dict/list/set>
- 'in' pode usar um gerador.Esta regra foi abandonada na versão 3.4.0, pois promovia um aumento na preguiça que poderia gerar bugs.
<list/reversed>
desnecessária em torno de sorted(). É desnecessário usar list()
em torno de sorted()
pois ele já retorna uma lista. Também é desnecessário usar reversed()
em torno sorted()
pois este último possui um argumento reverse
. Por exemplo:
list(sorted([2, 3, 1]))
como sorted([2, 3, 1])
reversed(sorted([2, 3, 1]))
como sorted([2, 3, 1], reverse=True)
reversed(sorted([2, 3, 1], reverse=True))
como sorted([2, 3, 1])
<list/reversed/set/sorted/tuple>
desnecessária dentro de <list/set/sorted/tuple>
(). É desnecessário fazer dupla conversão ou processamento duplo de iteráveis, agrupando as funções listadas em list
/ set
/ sorted
/ tuple
. Por exemplo:
list(list(iterable))
como list(iterable)
list(tuple(iterable))
como list(iterable)
tuple(list(iterable))
como tuple(iterable)
tuple(tuple(iterable))
como tuple(iterable)
set(set(iterable))
como set(iterable)
set(list(iterable))
como set(iterable)
set(tuple(iterable))
como set(iterable)
set(sorted(iterable))
como set(iterable)
set(reversed(iterable))
como set(iterable)
sorted(list(iterable))
como sorted(iterable)
sorted(tuple(iterable))
como sorted(iterable)
sorted(sorted(iterable))
como sorted(iterable)
sorted(reversed(iterable))
como sorted(iterable)
<reversed/set/sorted>
().É desnecessário reverter a ordem de um iterável, pois passá-lo para uma das funções listadas irá alterar a ordem novamente. Por exemplo:
set(iterable[::-1])
como set(iterable)
sorted(iterable)[::-1]
como sorted(iterable, reverse=True)
reversed(iterable[::-1])
como iterable
<dict/list/set>
- reescreva usando <dict/list/set>
(). É desnecessário usar uma compreensão de dict/list/set para construir uma estrutura de dados se os elementos permanecerem inalterados. Envolva o iterável com dict()
, list()
ou set()
. Por exemplo:
{a: b for a, b in iterable}
como dict(iterable)
[x for x in iterable]
como list(iterable)
{x for x in iterable}
como set(iterable)
map
- reescrever usando uma expressão geradora/compreensão <list/set/dict>
. map(func, iterable)
tem ótimo desempenho quando func
é uma função integrada e faz sentido se sua função já tiver um nome. Mas se sua função for lambda
, é mais rápido usar uma expressão geradora ou uma compreensão, pois evita a sobrecarga da chamada de função. Por exemplo:
map(lambda x: x + 1, iterable)
para (x + 1 for x in iterable)
map(lambda item: get_id(item), items)
para (get_id(item) for item in items)
list(map(lambda num: num * 2, nums))
para [num * 2 for num in nums]
set(map(lambda num: num % 2 == 0, nums))
para {num % 2 == 0 for num in nums}
dict(map(lambda v: (v, v ** 2), values))
para {v : v ** 2 for v in values}
<dict/dict comprehension>
desnecessário passado para dict() - remova a chamada externa para dict() É desnecessário usar um dict
em torno de um dict literal ou de uma compreensão de dict, pois qualquer uma das sintaxes já constrói um dict. Por exemplo:
dict({})
como {}
dict({"a": 1})
como {"a": 1}
<any/all>
() evita curto-circuito - reescreva como um gerador. Usar uma compreensão de lista dentro de uma chamada para any()
/ all()
evita curto-circuito quando um valor True
/ False
é encontrado. A lista inteira será construída antes de chamar any()
/ all()
, potencialmente desperdiçando work.part-way. Reescreva para usar uma expressão geradora, que pode parar no meio do caminho. Por exemplo:
all([condition(x) for x in iterable])
como all(condition(x) for x in iterable)
any([condition(x) for x in iterable])
como any(condition(x) for x in iterable)
É desnecessário usar uma compreensão de dict para construir um dict com todos os valores definidos para a mesma constante. Use dict.fromkeys()
em vez disso, que é mais rápido. Por exemplo:
{x: 1 for x in iterable}
como dict.fromkeys(iterable, 1)
{x: None for x in iterable}
como dict.fromkeys(iterable)