编写高质量Python程序的91个建议

书籍信息

  • 书名:编写高质量代码 改善Python程序的91个建议
  • 作者:张颖、赖勇浩
  • 出版社:机械工业出版社

笔记部分

建议1:理解Pythonic概念

Pythonic可以定义为:充分体现Python自身特色的代码风格。
推荐阅读:PEP 8 – Style Guide for Python Code

建议2:编写Pythonic代码
  1. 避免只用大小写来区分不同的对象。
  2. 避免使用容易引起混淆的名称如字母’O’的大小写和字母’L’的小写‘l’。
  3. 不要害怕过长的变量名,变量名易于理解最重要。
建议3:理解Python与C语言的不同之处
  1. “缩进"与”{ }"
    C、C++、Java等语言使用花括号{}来分隔代码,Python则采用严格的缩进方式(4 spaces 或者 1 tab)注意空格和tab不能混用。
  2. 单引号(’)和双引号(")
    C中单引号代表字符,双引号表示字符串,而在Python中,单双引号无明显区别。
  3. 三元操作符(?:)
    三元操作符为if…else的简写方法,语法形式为C?X:Y,表示当C为True取X,反之取Y。在Python中没有三元操作符,但有等价的形式:X if C else Y。
  4. switch… case
    Python中没有像C语言那样的条件分支语句,但是可以使用if…elif语句来实现同样的功能。
建议4:在代码中适当添加注释

Python中有三种形式的代码注释:块注释、行注释以及文档注释。
使用注释的建议有以下:

  1. 仅仅注释那些复杂的操作、算法,还有不够一目了然的代码。
  2. 注释和代码隔开一定的距离,不要过于紧凑,块注释后最好留几行空白。
  3. 给外部可访问的函数和方法添加文档注释。
建议5:通过适当添加空行使代码布局更为优雅、合理

下图可供参考
编写高质量Python程序的91个建议

建议6:编写函数的4个原则
  1. 函数设计要尽量短小,嵌套层次不宜过深。
  2. 函数声明应做到合理、简单、易于使用(函数名易于理解、参数简洁)。
  3. 函数参数设计应该考虑向后兼容(易于后续版本开发)。
  4. 一个函数只做一件事。尽量保证函数语句粒度的一致性。
建议7:将常量集中到一个文件

很少用到这一点,可以用过自定义类实现常量功能。

建议8:利用assert语句来发现问题

断言(assert)在很多语言中都存在,主要为调试程序服务,能够快速方便检查程序的异常或不恰当的输入等。
要注意的是使用assert是有代价的,它会对性能产生一定的影响,可以不用尽量不用。

建议9:数据交换值的时候不推荐使用中间变量

在Python,交换两个变量的值不需要中间变量

a = 10
b = 11

#不推荐的做法
tmp = a        
a = b
b = tmp       

#pythonic的交换方式,无需中间变量且效率更高
a, b = b, a    
建议10:充分利用Lazy evaluation的特性

Lazy evaluation可以理解为延迟计算或惰性计算,可带来的好处有两个方面:

  1. 避免不必要的计算,提升效率
    对Python中的条件表达式 if x and y , 当x为False的情况下直接返回False,程序不会计算y表达式的值。对于if x or y, 当x为True时,也不会计算y表达式的值并直接返回True。
  2. 节省空间,使无限循环的数据结构称为可能
    生成器了解一下?Python迭代器和生成器
建议11:理解枚举替代实现的缺陷
建议12:不推荐使用type来进行类型检查
建议13:尽量转换为浮点类型后再做除法
建议14:警惕eval()的安全漏洞
建议15:使用enumerate()获取序列迭代的索引和值
建议16:分清=与is的适用场景
建议17:考虑兼容性,尽可能使用Unicode
建议18:构建合理的包层次来管理module
建议19:有节制地使用from…import语句
建议20:优先使用absolute import来导入模块
建议21:i+=1 不等于 ++i
建议22:使用with自动关闭资源
建议23:使用else子句简化循环(异常处理)
建议24:遵循异常处理的几点基本原则
建议25:避免finally中可能发生的陷阱
建议26:深人理解None,正确判断对象是否为空
建议27:连接字符串应优先使用join而不是+
建议28:格式化字符串时尽量使用.format方式而不是%
建议29:区别对待可变对象和不可变对象
建议30:[]、()和{}: 一致的容器初始化形式
建议31:记住函数传参既不是传值也不是传引用
建议32:警惕默认参数潜在的问题
建议33:慎用变长参数
建议34:深入理解str()和repr()的区别
建议35:分清staticmethod和classmethod的适用场景
建议36:掌握字符串的基本用法
建议37:按需选择sort()或者sorted()
建议38:使用copy模块深拷贝对象
建议39:使用Counter进行计数统计
建议40:深入掌握ConfigParser
建议41:使用argparse处理命令行参数
建议42:使用pandas处理大型CSV文件
建议43:一般情况使用ElementTree解析XML
建议44:理解模块pickle优劣
建议45:序列化的另一个不错的选择—JSON
建议46:使用traceback获取栈信息
建议47:使用logging记录日志信息
建议48:使用threading模块编写多线程程序
建议49:使用Queue使多线程编程更安全
第5章 设计模式
建议50:利用模块实现单例模式
建议51:用mixin模式让程序更加灵活
建议52:用发布订阅模式实现松耦合
建议53:用状态模式美化代码
第6章 内部机制
建议54:理解build-in objects
建议55:init() 不是构造方法
建议56:理解名字查找机制
建议57:为什么需要self参数
建议58:理解MRO与多继承
建议59:理解描述符机制
建议60:区别getattr()和getattribute()方法
建议61:使用更为安全的property
建议62:掌握metaclass
建议63:熟悉Python对象协议
建议64:利用操作符重载实现中缀语法
建议65:熟悉Python的迭代器协议
建议66:熟悉Python的生成器
建议67:基于生成器的协程及greenlet
建议68:理解GIL的局限性
建议69:对象的管理与垃圾回收
第7章 使用工具辅助项目开发
建议70:从PyPI安装包
建议71:使用pip和yolk安装、管理包
建议72:做paster创建包
建议73:理解单元测试概念
建议74:为包编写单元测试
建议75:利用测试驱动开发提高代码的可测性
建议76:使用Pylint检查代码风格
建议77:进行高效的代码审查
建议78:将包发布到PyPI
第8章 性能剖析与优化
建议79:了解代码优化的基本原则
建议80:借助性能优化工具
建议81:利用cProfile定位性能瓶颈
建议82:使用memory_profiler和objgrash剖析内存使用
建议83:努力降低算法复杂度
建议84:掌握循环优化的基本技巧
建议85:使用生成器提高效率
建议86:使用不同的数据结构优化性能
建议87:充分利用set的优势
建议88:使用meltiprocessing克服GIL的缺陷
建议89:使用线程池提高效率
建议90:使用C/C++模块扩展提高性能
建议91:使用Cython编写扩展模块