一個 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)