Chapter 1 Pythonic Thinking
1. 确认自己所用的 Python 版本
- 2to3、six 等工具可用于 Python 2 到 Python 3 的代码适配。
2. 遵循 PEP8 风格指南
- 每行字符数不超过 79;
- 函数与类之间用两个空行隔开,同一类中的方法之间用一个空行隔开;
- 使用索引时,不在两边加空格;
- 函数、变量、属性使用小写、下划线;
- 受保护属性用单个下划线开头,私有属性用两个下划线开头;
- 类与异常使用大写、无下划线;
- 模块级别的常量使用全部大写、下划线;
- 不用检测长度的方法(
len)来判断序列是否为空; - 引入模块时使用绝对名称,而不根据当前模块的路径来使用相对名称。如果一定要用相对名称,则使用
.表示; import语句分为三部分:标准库、第三方与自用模块,部分内按字母顺序排列。
3. 了解 bytes, str, Unicode 的区别
bytes实例包含原始的 8 位字符值,str实例包含 Unicode 字符;- 前者转化为后者需要解码(
decode),后者转化为前者需要编码(encode),结果由编解码方式决定; - Python 程序中要把编解码操作放在最外围,核心部分应当使用 Unicode 字符类型,不依赖于编码的形式;
bytes和str都可以使用加法(连接)、比较大小、格式化字符串(%),但不同类型不可以:- 不同类型可以使用
==比较,但结果永远为 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,值为左侧变量的值; - 常用于
if、while等语句的条件判断处,实现 C/C++ 中赋值后判断的功能; - 可优化嵌套 if-else 语句,合并成
elif条件。