一个 flake8 插件,可以帮助您编写更好的列表/集合/字典理解。
检查 Django 项目?查看我的书《Boost Your Django DX》,其中涵盖了 Flake8 和许多其他代码质量工具。
支持 Python 3.9 至 3.13。
首先,使用pip
安装:
python -m pip install flake8-comprehensions
其次,如果您定义了 Flake8 的select
设置,请为其添加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>
文字 - 重写为字典文字。没有必要在调用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()
(),因为后者有一个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>
() 内的 iterable 不必要的下标反转。当将可迭代对象传递到列出的函数之一将再次更改顺序时,无需反转可迭代对象的顺序。例如:
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()
包装可迭代对象。例如:
{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>
理解重写。当func
是内置函数时, 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({"a": 1})
重写为{"a": 1}
<any/all>
() 中不必要的列表理解可防止短路 - 重写为生成器。在对any()
/ all()
的调用中使用列表理解可以防止找到True
/ False
值时发生短路。整个列表将在调用any()
/ all()
之前构建,可能会浪费 work.part-way。重写以使用生成器表达式,该表达式可以中途停止。例如:
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.fromkeys()
代替,这样更快。例如:
{x: 1 for x in iterable}
重写为dict.fromkeys(iterable, 1)
{x: None for x in iterable}
重写为dict.fromkeys(iterable)