Плагин flake8, который поможет вам лучше писать списки/наборы/диктовки.
Линтинг проекта Django? Прочтите мою книгу Boost Your Django DX, в которой рассказывается о Flake8 и многих других инструментах качества кода.
Поддерживается Python 3.9–3.13.
Сначала установите с помощью pip
:
python -m pip install flake8-comprehensions
Во-вторых, если вы определяете настройку select
Flake8, добавьте к ней префикс C4
. В противном случае плагин должен быть активен по умолчанию.
<list/set/dict>
.Правила:
Нет необходимости использовать list
, set
или dict
вокруг выражения генератора, поскольку для этих типов существуют эквивалентные понимания. Например:
list(f(x) for x in foo)
как [f(x) for x in foo]
set(f(x) for x in foo)
как {f(x) for x in foo}
dict((x, f(x)) for x in foo)
как {x: f(x) for x in foo}
<set/dict>
.Правила:
Нет необходимости использовать понимание списка внутри вызова set
или dict
, поскольку для этих типов существуют эквивалентные понимания. Например:
set([f(x) for x in foo])
как {f(x) for x in foo}
dict([(x, f(x)) for x in foo])
как {x: f(x) for x in foo}
<list/tuple>
— перепишите как литерал <set/dict>
.<list/tuple>
— перепишите как набор литералов.<list/tuple>
— перепишите как литерал dict. Нет необходимости использовать литерал списка или кортежа внутри вызова set
или dict
. Например:
set([1, 2])
как {1, 2}
set((1, 2))
как {1, 2}
set([])
как set()
dict([(1, 2)])
как {1: 2}
dict(((1, 2),))
как {1: 2}
dict([])
как {}
<dict/list>
— <builtin>
может использовать генераторЭто правило было исключено в версии 3.4.0, поскольку оно способствовало увеличению лени, что могло привести к ошибкам.
<dict/list/tuple>
— перепишите как литерал. Вызов, например, dict()
медленнее, чем использование пустого литерала, поскольку имя dict
необходимо искать в глобальной области видимости в случае его повторного привязки. То же самое и с двумя другими основными типами. Например:
dict()
как {}
dict(a=1, b=2)
как {"a": 1, "b": 2}
list()
как []
tuple()
как ()
<list/tuple>
передан в <list/tuple>
() - <advice>
.Правила:
<list/tuple>
передан в tuple() — <advice>
.<advice>
. Где <advice>
:
<list/tuple>
()<list/tuple>
Нет необходимости использовать литерал списка или кортежа при вызове list
или tuple
, поскольку для этих типов существует литеральный синтаксис. Например:
tuple([1, 2])
как (1, 2)
tuple((1, 2))
как (1, 2)
tuple([])
как ()
list([1, 2])
как [1, 2]
list((1, 2))
как [1, 2]
list([])
как []
Нет необходимости использовать list
для понимания списка, поскольку без него он эквивалентен. Например:
list([f(x) for x in foo])
как [f(x) for x in foo]
<dict/list/set>
— 'in' может использовать генератор.Это правило было исключено в версии 3.4.0, поскольку оно способствовало увеличению лени, что могло привести к ошибкам.
<list/reversed>
для sorted(). Нет необходимости использовать list()
вместо sorted()
поскольку он уже возвращает список. Также нет необходимости использовать reversed()
вместо sorted()
поскольку последний имеет reverse
аргумент. Например:
list(sorted([2, 3, 1]))
как sorted([2, 3, 1])
reversed(sorted([2, 3, 1]))
как sorted([2, 3, 1], reverse=True)
reversed(sorted([2, 3, 1], reverse=True))
как sorted([2, 3, 1])
<list/reversed/set/sorted/tuple>
внутри <list/set/sorted/tuple>
(). Нет необходимости выполнять двойное приведение или двойную обработку итераций, заключая перечисленные функции в list
/ set
/ sorted
/ tuple
. Например:
list(list(iterable))
как list(iterable)
list(tuple(iterable))
как list(iterable)
tuple(list(iterable))
как tuple(iterable)
tuple(tuple(iterable))
как tuple(iterable)
set(set(iterable))
как set(iterable)
set(list(iterable))
как set(iterable)
set(tuple(iterable))
как set(iterable)
set(sorted(iterable))
как set(iterable)
set(reversed(iterable))
как set(iterable)
sorted(list(iterable))
как sorted(iterable)
sorted(tuple(iterable))
как sorted(iterable)
sorted(sorted(iterable))
как sorted(iterable)
sorted(reversed(iterable))
как sorted(iterable)
<reversed/set/sorted>
().Нет необходимости менять порядок итерации, поскольку передача ее в одну из перечисленных функций снова изменит порядок. Например:
set(iterable[::-1])
как set(iterable)
sorted(iterable)[::-1]
как sorted(iterable, reverse=True)
reversed(iterable[::-1])
как iterable
<dict/list/set>
— перепишите с помощью <dict/list/set>
(). Нет необходимости использовать понимание dict/list/set для построения структуры данных, если элементы не изменились. Вместо этого оберните итерацию с помощью dict()
, list()
или set()
. Например:
{a: b for a, b in iterable}
как dict(iterable)
[x for x in iterable]
как list(iterable)
{x for x in iterable}
как set(iterable)
map
— перепишите, используя выражение генератора/понимание <list/set/dict>
. map(func, iterable)
имеет отличную производительность, когда func
является встроенной функцией, и это имеет смысл, если у вашей функции уже есть имя. Но если ваша функция является lambda
, быстрее использовать выражение-генератор или понимание, поскольку это позволяет избежать накладных расходов на вызов функции. Например:
map(lambda x: x + 1, iterable)
на (x + 1 for x in iterable)
map(lambda item: get_id(item), items)
на (get_id(item) for item in items)
list(map(lambda num: num * 2, nums))
на [num * 2 for num in nums]
set(map(lambda num: num % 2 == 0, nums))
на {num % 2 == 0 for num in nums}
dict(map(lambda v: (v, v ** 2), values))
на {v : v ** 2 for v in values}
<dict/dict comprehension>
передан в dict() — удалите внешний вызов dict(). Нет необходимости использовать dict
вокруг литерала dict или понимания dict, поскольку любой синтаксис уже создает dict. Например:
dict({})
как {}
dict({"a": 1})
как {"a": 1}
<any/all>
() предотвращает короткое замыкание — перепишите как генератор. Использование понимания списка внутри вызова any()
/ all()
предотвращает короткое замыкание при обнаружении значения True
/ False
. Весь список будет создан перед вызовом any()
/ all()
, что может привести к потере работы. Перепишите, чтобы использовать выражение-генератор, которое может остановиться на полпути. Например:
all([condition(x) for x in iterable])
как all(condition(x) for x in iterable)
any([condition(x) for x in iterable])
как any(condition(x) for x in iterable)
Нет необходимости использовать понимание dict для создания dict со всеми значениями, установленными в одну и ту же константу. Вместо этого используйте dict.fromkeys()
, что быстрее. Например:
{x: 1 for x in iterable}
как dict.fromkeys(iterable, 1)
{x: None for x in iterable}
как dict.fromkeys(iterable)