我当前在 Python 脚本里保持的骨架大致如下:

#!/usr/bin/env python3
# coding=utf-8


def main():
    ...


if __name__ == "__main__":
    main()

下面逐条解释这些选择,以及我在缩进、引号、空白上的习惯。

shebang

#!/usr/bin/env python3 只在 Unix/类 Unix 系统上生效,Windows 会直接忽略这一行。它的作用是让内核用 env 找到 python3 来执行脚本,而不是硬编码 /usr/bin/python3 这样可能不存在的路径。对要用 ./script.py 直接跑脚本的人来说,这行算基本礼貌,省去先敲 python3 的步骤。

如果你的脚本只跑在 Windows 上,写不写无所谓;但只要有可能跨平台,保留它没有坏处。

编码声明

Python 2 默认源文件编码是 ASCII,要写中文就必须在文件头加 # coding: utf-8。另一种常见写法 # -*- coding: utf-8 -*- 里的 -*- 纯粹是装饰,Emacs 早期风格延续下来的,我更喜欢直接写成 # coding=utf-8

Python 3 已经默认 UTF-8,理论上去掉这行也没问题。但考虑到仍有人在用 Windows 7 或某些特殊环境(比如系统 locale 不是 UTF-8 的 CI 容器),带上这行能够避免 GBK 环境解析源文件时报错。保留它成本为零,兼容性却多一层。

程序入口

把主流程写进 main() 然后靠 if __name__ == "__main__" 调用,这是 Python 社区沉淀下来的习惯。好处至少有三个:

  1. 函数内部的变量是局部变量,不会漏成全局变量污染模块空间。
  2. 模块可以在被 import 时不执行任何副作用,同时又能独立运行调试。
  3. 与其他语言(C/Java/Go 等)的入口函数命名保持一致,降低阅读切换成本。

if __name__ == "__main__" 本身是 Python 运行时的内建机制:当脚本作为主程序运行时,解释器会把 __name__ 设成 "__main__";当被导入时,__name__ 则是模块名。这个差异刚好用来区分两种用途。

引号

我个人默认用双引号 "。Black 格式化工具的默认行为也是双引号,除非字符串内含有双引号导致转义过多,才会临时切换到单引号。我自己的处理方式更绝对一点:即使需要在字符串内部写双引号,我也会用转义 \" 来保持外层统一。

另有一种流派:用双引号包裹面向人的字符串(比如日志、提示),单引号包裹面向机器的字符串(比如字典 key、正则),这能在语义上多传递一层信息。我个人不反对这种分法,但前提是整个项目能达成一致,否则混用不如统一。

缩进

Python 用缩进代替花括号来划分代码块。好处是强制统一外观,坏处是深层嵌套会迅速吃掉横向空间。我一般控制最多三层逻辑缩进——如果发现要写到第四层,就拆分函数或者用 any/alldict.get 之类的手法把判断提前消掉。

一个例子:多层 if 嵌套可以改成守卫语句直接 returnraise,缩进立刻回到可控范围。

行宽与换行

我一直遵守 79 字符的行宽限制。这个数字来自 PEP 8,最初是对 80 列终端的兼容,但即便在今天,窄行高密度的窗口排列也依然受益于此。

超出 79 字符时,表达式用括号隐式续行优先于反斜杠 \。对于容器字面量,直接用元素间逗号换行:

data = [
    "first",
    "second",
    "third",
]

这种写法在 diff 时只改一行,不会动到前后的逗号。

空白与注释

我习惯在逻辑块之间空一行,逗号后留一个空格,运算符两侧也各留一个空格。这些细微空白对人眼解析速度的帮助远大于看起来的“浪费”。

注释我尽量用英文,即便团队内部中文交流也没问题,但英文注释能避免编码声明之外的编码猜测,也方便与开源社区衔接。如果必须用中文注释,我会在中文与英文单词/数字之间加一个半角空格,保持文字的呼吸感。

这种空格习惯不止是在注释里,任何中英文混排的地方都值得保持。

以上规则没有一个是为了“正确”而存在,它们只是我在多次踩坑和阅读他人代码后收敛出来的最小共识。一致性本身,就是最好的可读性。