1. 确认自己所用的 Python 版本

  • 2to3、six 等工具可用于 Python 2 到 Python 3 的代码适配。

2. 遵循 PEP8 风格指南

PEP8

  • 每行字符数不超过 79
  • 函数与类之间用两个空行隔开,同一类中的方法之间用一个空行隔开;
  • 使用索引时,不在两边加空格;
  • 函数、变量、属性使用小写、下划线
  • 受保护属性用单个下划线开头,私有属性用两个下划线开头;
  • 类与异常使用大写、无下划线;
  • 模块级别的常量使用全部大写、下划线
  • 不用检测长度的方法(len)来判断序列是否为空
  • 引入模块时使用绝对名称,而不根据当前模块的路径来使用相对名称。如果一定要用相对名称,则使用 . 表示;
  • import 语句分为三部分:标准库、第三方与自用模块,部分内按字母顺序排列。

3. 了解 bytes, str, Unicode 的区别

  • bytes 实例包含原始的 8 位字符值,str 实例包含 Unicode 字符;
  • 前者转化为后者需要解码(decode),后者转化为前者需要编码(encode),结果由编解码方式决定;
  • Python 程序中要把编解码操作放在最外围,核心部分应当使用 Unicode 字符类型,不依赖于编码的形式;
  • bytesstr 都可以使用加法(连接)、比较大小、格式化字符串(%),但不同类型不可以:
    • 不同类型可以使用 ` == ` 比较,但结果永远为 False
    • 可以在格式化 str 时使用 bytes,但会使用 __repr__ 的结果,不符合预期。
  • open 函数默认使用 UTF-8 编码格式操作文件,encoding='utf-8',此时必须传入/读取包含 Unicode 字符的 str 实例。要使用二进制形式(bytes)读取/写入,必须采用二进制写入模式 'wb'
  • 可以使用 python3 -c 'import locale; print(locale.getpreferredencoding())' 来查看系统默认使用的编码方式。

4. 推荐使用 f-string 格式化字符串,而非 %str.format

  • 最常见方法是 %,语法来自于 printf。同一变量必须在字符串与格式化元组中各指定一次,在调整打印变量的顺序时比较麻烦,用于格式化的变量元组可能因添加附加操作而变得过长,重复打印变量时也需要重复罗列;
  • % 操作符也支持使用字典而不是元组来格式化字符串,在字符串中使用类似 %(value).2f 的格式来指定变量名。仍存在格式化表达式过长的问题;
  • str.format 借助了 format 的结果,可以通过类似 {:<10.2f} 的形式指定格式。{} 的转义符为 { {}}。可以指定位置编号 {0}, {1}。也可以在 str.format 中使用关键字参数,并扩展格式字符串位置的表达式 {menu[oyster]}。不过也存在过长的问题;
  • f-string 中的格式字符串与上面相同 {key!r:<10}。其中的格式参数也可动态指定 {number:.{places}f}。更简洁,拆分多行更直观
  • 新的格式字符串句法:, 表示千位分隔符,^ 表示居中。{name!r} 表示使用 __repr__ 而非 __str__ 来翻译为字符串。

5. 用辅助函数来取代复杂的表达式

  • 空字符串、空列表、零值都会评估为 False,因此可以or 来指定缺省值
  • 如果表达式比较复杂,那么就需要考虑拆解成小块,避免过度运用特性。

6. 使用元组拆包替代索引

  • 元组拆包的应用:排序中值的交换,for 迭代中的直接拆包

7. 尽量用 enumerate 取代 range

  • enumerate(iterable, i) 把各种可迭代对象包装成生成器,每次产出一对值,表示索引和迭代器产出值。

8. 用 zip 函数同时遍历两个迭代器

  • 如果迭代器长度不等,则会提前终止(依据较短的);
  • 可以使用 itertools.zip_longest 遍历多个不等长迭代器,使用 fillvalue 补充缺省部分。

9. 不要在 for 和 while 循环后面写 else 块

  • 循环不通过 break 退出时,才会执行 else 块;
  • try/except/else 中的 else 块会在没有异常抛出时执行,为 except 的互补块。

10. 使用赋值表达式来避免重复

  • (从 Python 3.8 起)赋值表达式 a := b 读作 a walrus b,值为左侧变量的值
  • 常用于 ifwhile 等语句的条件判断处,实现 C/C++ 中赋值后判断的功能;
  • 可优化嵌套 if-else 语句,合并成 elif 条件。