Effective Python 第2版 (Brett Slatkin)

编写高质量 Python 代码的 90 个有效方法

作为一名开发者,学习一门语言通常会经历几个阶段。最开始,我们关注的是:“这个功能怎么实现?”然后逐渐编程:“这个实现是否合理?”再进一步:“这个设计能否支撑未来几年的维护?”Python也是如此。初学阶段,我们学习变量、函数、类、模块,然后利用框架和库快速完成需求。但真正进入工程开发后,会遇到更多问题:

  • 为什么有些代码难以测试?
  • 为什么简单的修改会影响到整个系统?
  • 为什么别人写的代码看起来更自然?
  • 为什么同样的功能,有些实现更加高效?

这些问题的答案,往往隐藏在语言细节和工程实践中,Effective Python 编写高质量 Python 代码的 90 个有效方法便是一份Python工程实践指南。

第 1 章 培养 Pythonic 思维

第 10 条 用赋值表达式减少重复代码

第 2 章 列表与字典

第 11 条 学会对序列做切片

liststrbytes都可以获取原序列的某个子集(即切片)。凡是实现了__getitem____setitem__两个特殊方法的类都可以切割[第 43 条 自定义的容器类型应该从 collections.abc 继](#第 43 条 自定义的容器类型应该从 collections.abc 继承)。

切割时所用的下标可以越界,但直接访问列表却不行,会让程序抛出异常。

切割出来的列表是一份全新的列表。如果元素是非引用类型,则不会影响到原列表。

把切片放在赋值符号的左侧可以将原列表中这段范围内的元素用赋值符号右侧的元素替换掉,但可能会改变原列表的长度。

第 12 条 不要在切片里同时指定起止下标与步进

不要把起止下标与步进值同时写在切片里。如果必须指定步进,尽量采用正数,且把起止下标都留空。若必须同时使用步进值与起止下标,应该分成两次来写。

1
2
3
4
5
x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

y = x[::2]

z = y[1:-1]

若程序没有那么多时间或内存分两步操作,可改用 itertools 模块中的 islice 方法[第36条 考虑用itertools拼装迭代器与生成器](#第36条 考虑用itertools拼装迭代器与生成器),其起止位置与步进值不能是负数。

第 9 章 测试与调试

第 80 条 考虑用 pdb 做交互调试

Python 内置的breakpint函数可以用来触发调试器。该函数的效果与先引入内置的 pdb 模块然后运行set_trace函数效果是一样的。

一旦运行breakpoint函数,程序会在即将执行下一条语句的地方暂停,运行 Python 程序的终端窗口会进入交互调试界面。

PDB交互调试界面
PDB交互调试界面

事后调试(post-mortem debugging),当发现程序抛出异常并崩溃后,想通过调试器看到抛出异常的那一刻究竟是什么样的。大概率此时我们也不确定应该在哪里调用breakpoint函数。

此时可以运行python -m pdb -c continue <program_path>命令,会让 pdb 在启动受测程序之后立刻向前推进,直到遇到断点或出现异常为止。

还有一种方法触发事后调试机制,就是先在普通的 Python 解释器里执行受测代码,待遇到未被捕获的异常后,再引入 pdb 模块并调用其pm函数(import pdb; pdb.pm())。

出现未捕获异常后进入PDB
出现未捕获异常后进入PDB

参考

Effective Python 编写高质量 Python 代码的 90 个有效方法


相关内容

请作者喝杯咖啡!
AndyFree96 支付宝支付宝
AndyFree96 微信微信