4.《Python高质量代码的91个建议》库

1 建议 36:掌握字符串的基本用法

查找与替换、切割、删除空白符等待

2 建议 37:按需选择 sort() 或者 sorted()

sort只能应用在列表list上,而sorted可以对所有可迭代的对象进行排序的操作

sort方法会在原list上直接进行排序,不会创建新的list。

sorted方法不会对原来的数据做任何改动,排序后的结果是新生成的。

sorted() 函数功能强大,可以针对不同的数据结构进行排序,还可以自定义比较函数。

3 建议 38:使用 copy 模块深拷贝对象

  • 浅拷贝(shallow copy):构造一个新的复合对象并将从原对象中发现的引用插入该对象中。浅拷贝的实现方式有多种,如工厂函数、切片操作、copy 模块中的 copy 操作等。

  • 深拷贝(deep copy):也构造一个新的复合对象,但是遇到引用会继续递归拷贝其所指向的具体内容,也就是说它会针对引用所指向的对象继续执行拷贝,因此产生的对象不受其他引用对象操作的影响。深拷贝的实现需要依赖 copy 模块的 deepcopy() 操作。

4 建议 39:使用 Counter 进行计数统计

推荐使用collections.Counter

from collections import Counter
some_data = ["a", "2", 2, 4, 5, "2", 4, "a", 5, "d", "z", "a"]
print(Counter(some_data))
#output
Counter({'a': 3, '2': 2, 4: 2, 5: 2, 2: 1, 'd': 1, 'z': 1})

5 建议 40:深入掌握 ConfigParser

ConfigParser可以对 INI 结构的配置文件进行解析

INI 结构的配置文件示例:

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes

[bitbucket.org]
User = hg

[topsecret.server.com]
Port = 50022
ForwardX11 = no

具体可参考configparser文档--配置文件解析器

6 建议 41:使用 argparse 处理命令行参数

  • 语法直观,支持类型丰富(数值类型、文件类型)
  • 支持必填参数、参数分组、子命令
  • 自动生成帮助和使用手册
  • 传入无效参数时报出错误信息

具体可参考Argparse文档--命令行选项、参数和子命令解析器

7 建议 42:使用 pandas 处理大型 CSV 文件

CSV(Comma Separated Values)是一种以逗号作为分隔的纯文本格式文件

Pandas通过两种基本数据类型Series 和 DataFrame,完成各种数据分析任务

Pandas支持文件类型丰富、数据处理灵活,很多计算通过Cython 高效实现

8 建议 43:使用 ElementTree 解析 XML

xml.etree.ElementTree模块实现了一个简单高效的API,用于解析和创建XML数据

XML结构的文件示例:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank>1</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank>4</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
</data>

具体可参考xml.etree.ElementTree文档--ElementTree XML API

9 建议 44:理解模块 pickle 优劣

模块 pickle 实现了对一个 Python 对象结构的二进制序列化和反序列化。

  • pickle 不能保证操作的原子性,避免pickle 调用时发生异常后或进行对象的深递归
  • 不要随便反序列化不可信的数据,pickle 存在安全性问题
  • pickle 协议是 Python 特定的,与其他语言可能存在兼容问题

具体可参考pickle文档--Python 对象序列化

10 建议 45:序列化的另一个选择——JSON

模块 json 是一个允许JSON序列化和反序列化的标准库模块。

json vs pickle

  • json是一个文本序列化格式; pickle是一个二进制序列化格式
  • json的存储格式可读性更为友好,容易修改
  • pickle协议是 Python 特定的,而json跨平台跨语言
  • json支持大部分的 Python 内置类型,而pickle支持的数据类型更丰富

具体可参考json文档--JSON 编码和解码器

11 建议 46:使用 traceback 获取栈信息

模块traceback提供了一个标准接口来提取、格式化和打印 Python 程序的堆栈跟踪结果。

具体可参考traceback文档--打印或检索堆栈回溯

12 建议 47:使用 logging 记录日志信息

logging模块为应用与库定义了实现灵活的事件日志系统的函数与类

级别 数值 使用情形
CRITICAL 50 严重的错误,或者程序本身不能够继续运行
ERROR 40 由于某些严重的问题,程序中的一些功能受到影响
WARNING 30 一些不可预见或将发生的问题,如磁盘空间低等,但不影响程序的运行
INFO 20 正常的信息
DEBUG 10 详细的信息,在追踪问题的时候使用
NOTSET 0 未设定级别的信息

三个建议:

  • 尽量为 logging 取一个名字而不是采用默认,这样当在不同的模块中使用的时候,其他模块只需要使用以下代码就可以方便地使用同一个 logger,因为它本质上符合单例模式:
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
  • 为了方便地找出问题所在,logging 的名字建议以模块或者 class 来命名。Logging 名称遵循按 "." 划分的继承规则,根是 root logger,logger a.b 的父 logger 对象为 a。

  • Logging 只是线程安全的,不支持多进程写入同一个日志文件,因此对于多个进程,需要配置不同的日志文件。

具体可参考logging文档--Python 的日志记录工具

13 建议 48:使用 threading 模块编写多线程程序

1_study/ComputerScience/programming/进程、线程与协程#线程

14 建议 49:使用 Queue 使多线程编程更安全

queue模块实现了多生产者,多消费者队列。适用于信息必须安全地在多线程之间交换的情况。

具体可参考queue文档--一个同步的队列类

往年同期文章