使用 Ruff 拯救 Python 代码风格

使用 Ruff 尝试挽救稀巴烂的 Python 代码风格。

Ruff

众所周知,Python 工具链非常灾难。Ruff 作为 Astral 出品的略微能打的 Python 格式化工具,还是需要经过一些配置才能挽救 Python 的一些设计缺陷。

pyproject.toml 里可以直接配置 Ruff。

[tool.ruff]
# 在默认规则的基础上启用更多规则
# 如果想要覆盖默认规则,直接使用 lint.select
lint.extend-select = []

# 忽略特定规则
lint.ignore = []

# 特定配置项
lint."{...}" = true
Tip

查看 Ruff 的配置项 和支持的规则集

字符串隐式拼接

Python 提供字符串隐式拼接功能,连续的字符串会被拼成一个:

one_string = ("Life is short"
              "because I used Python")
assert type(one_string) is str

对于经常写一整个列表的字符串的我来说这个功能等同于自残,忘记一个逗号几乎难以发现列表里少了一个元素。 通过 Ruff 的 flake8-implicit-str-concat 扩展可以对所有的隐式拼接提出警告:

lint.extend-select = ["ISC"]
lint.flake8-implicit-str-concat.allow-multiline = false

意外的元组括号省略

Python 在很多情况下可以省略元组表达式周围的括号。在 numpy 取下标时这提供了很大的方便(比如 arr[x, y]),但有些时候修改代码忘了删某个逗号,就会造成神秘的 bug,特别是在返回值中:

return do_something_on(result, some_arg)
# 修改了一下但是忘记删逗号……
return result,
#            ^ 这里是个元组

启用 trailing-comma-on-bare-tuple 规则以彻底阻止这种情况,所有没有括号的元组都不允许有尾随逗号。

lint.extend-select = ["COM818"]

意义不明的规则

Python 有一些奇妙的代码风格规则管得十分宽。

首先关掉 E741 ambiguous-variable-name。这个规则不让把变量命名为 l, I 或者 O,因为容易混淆。把一个列表中间变量命名为 l,或者一个迭代器泛型命名为 I,或者一个输出泛型命名为 O,都十分合情合理。当今大家都在用能区分这几个字符的等宽字体了罢,写代码又不是选车牌😅……