前言
从刚发售那会,就看到有几位推友在推荐。刚开始还没特别感兴趣,第一眼印象:这不就是与 Fluent Python 类似的题材嘛,Fluent Python 都那么厚了,还能整出什么花来吗?我就没有买。
但是几天后,萝莉老师突然艾特我,“小圆,强推这本书啊”。按捺不住安利,仔细一看,原来是蓝鲸的大佬写的(离职前我刚好一度想活水到蓝鲸,最后还是没鼓起勇气去勾搭),看着目录好像也挺有东西,就迅速入了一本。后来公司的项目赶进度,也就每天中午午休的时间翻一翻,就这么零零散散地看了三个月,整本书翻了两遍,最近终于看完了。
总体而言,这本书给我的感觉跟 Fluent Python、Effective C++ 差不多。读完确实有收获,而且都挺实用的,但大多属于锦上添花。没见过这些技巧不影响你糊 CRUD,但是看完了可以让你的 CRUD 更好看、更好维护,也更不容易趟坑。
阅读笔记
大部分我自己已经熟知的技巧我没有整理进来。
变量与注释
- 如何命名变量,有一个可以参考的格式:定语+主语
- 注释应当解释背后的设计思路、代码的目的,或者起领读作用,而非逐句翻译代码本身
- 注释/文档应当着重描述函数的功能以及参数说明,不应过多描述函数的实现细节
- 变量的定义尽量靠近使用的地方
- 如有条件,可以实践先写注释,后写代码
- 如果发现你无法清晰地为一个将要新增的函数书写注释,那这个函数的功能定位很可能过于杂糅
数值与字符串
- 应当时刻注意浮点数的精度问题
- 如有必要可以使用
decimal.Decimal
- 如有必要可以使用
- 布尔值也是数字,在计数等场景下可以简化代码逻辑
- True == 1;False == 0
- 在大多数情况下,程序应当优先接收、处理普通字符串而非字节串
- 尽量避免“魔数”的存在——定义常量或枚举
- 为了美化代码,多行字符串有非预期的缩进时,可以使用
textwrap.dedent
来去除
条件分支控制流
- bisect 二分查找可以简化范围判断的重复代码
异常与错误处理
- 用
contextlib.contextmanager
配合yield
,可以简便地实现上下文管理器 - 避免抛出抽象级别高于、低于当前模块的异常
循环与可迭代对象
- 迭代器:必须同时实现
__iter__
与__next__
- 可迭代对象:只需要实现
__iter__
- 通过修饰可迭代对象来优化循环
- 类似于“漏斗”,层层筛选数据
函数
itertools.product
简化多层循环itertools.islice(seq, start, end, step)
实现隔行处理iter(callable, sentinel)
很少见的做法,当迭代到sentinel
时停止- 用函数
return
来实现“快速从多层循环中跳出” - 如果需要实现有状态的装饰器,可以采用闭包或者类的方式来保存状态
- 用
radon
工具来计算圈复杂度
装饰器
- 浅装饰器,深实现
- 装饰器仅仅是组装各种内部模块形成的轻量逻辑
面向对象编程
- RPC 应当让使用者清楚地认知到是 RPC
- 抽象类的子类化机制
__subclasshook__
:定义了判断一个类是否为本类子类的“鸭子类型”准则,该类无需拥有与本类的继承关系- 注意要遍历 mro
__init_subclass__
派生子类的钩子super()
不一定会调用自己的直接父类,而是按照最开始发起实例化的类的 mro 顺序依次触发- 继承不一定适用于所有情景,善用 Mixin 模式
- 对事物的行为建模,而非对事物建模
- 类方法的推荐组织顺序
__init__
- 对外 API
- 内部工具函数
- 其他魔术方法
- 用模块来实现单例
面向对象设计原则
SOLID 原则
- Single responsibility principle 单一职责原则
- 一个类应当仅有一个被修改的理由
- 如何解决
- 大类拆小类
- Open-closed principle 开闭原则
- 类应该对拓展开放,对修改封闭
- 找出类里容易发生变动的地方
- 可以在不修改某个类的前提下拓展其行为
- 典型例子是
sorted(iterable, *, key)
- 如何解决
- 让易变的逻辑可被外部定义
- 数据驱动
- 类应该对拓展开放,对修改封闭
- Liskov substitution principle 里氏替换原则
- 所有子类应当可以任意替换其父类使用,且不会破坏程序原本的功能
- Interface segregation principle 接口隔离原则
- 客户不应该依赖任何它不使用的方法
- 如何解决
- 拆接口
- Dependency inversion principle 依赖倒置原则
- 高层模块不应该依赖底层模块,二者都应该依赖抽象
- 如何解决
- 加抽象层
数据模型与描述符
@functools.total_ordering
可以一键补全所有缺失的比较函数- 只需要实现
__eq__
与任意一个大于小于判断函数
- 只需要实现
- 描述符:控制类属性的创建、获取、删除操作
- 很适合拿来写 ORM 框架!