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

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

这本书清楚地告诉我们如何改善Python代码的风格以及函数质量,了解符合Python风格的基础语言结构,编写“Pythonic”风格代码,提升Python的技能。本篇博客主要摘选部分的原则或者建议作详细描述,其他则作为简要略过。如有兴趣可以阅读原书。

用Pythonic方式思考

确定自己所用的Python版本

遵循PEP 8风格指南

《Python Enhancement Proposal #8》

  • 空格

    1. 使用space来表示缩进,而不要用tab
    2. 和语法相关的每一层缩进都用4个空格表示
    3. 每行的字符数不应超过79
    4. 对于占据多行的长表达式来说,除了首行之外的其余各行在通常的缩进级别上再缩进四个空格
    5. 文件中的函数与类之间应该用两个空行隔开
    6. 在同一个类中,个方法之间应该用一个空行隔开
    7. 在使用下表来获取列表元素、调用函数或给关键字参数赋值的时候,不要在两旁添加空格
    8. 为变量赋值的时候,赋值符号的左侧和右侧应该各自写上一个空格,而且只写一个就好
  • 命名

    1. 函数、变量以及属性应该用小写字母表示,各单词之间应该以下划线相连,如:abc_abc
    2. 受保护的实例属性,应该以单个下划线开头,如_abc
    3. 私有是的实例属性,应该以两个下划线开头,如__abc
    4. 类与异常,应该以每个单词首字母均大写的形式来命名:AbcAbc
    5. 模块级别的常量,应该全部采用大写字母来拼写
  • 表达式和语句

    1. 不要编写单行的if语句,for循环、while循环以及except复合语句,而且应该把这些语句分成多行来书写,以示清晰
    2. import语句应该总是放在文件头
    3. 引入模块的时候,总是应该使用绝对名称,而不应该根据当前模块路径来使用相对名称,如应写成from bar import foo而不是import bar

了解bytes、str和unicode的区别

用辅助函数来取代负复杂的表达式

了解切片的方法

  • 不要写多余的代码:当start索引为0,或end索引为序列长度时,应该将其省略
  • 切片操作不会计较start与end是否越界,这使得我们很容易就能从序列的前端或后端开始,对其进行范围固定的切片操作

在单次切片操作内,不要同时指定start、end和stride

如果指定了stride,那么代码会变得相当费解以及难理解,因此不应该把stride与start和end写在一起。如果非要用stride,那就尽量采用正值,同时省略start和end的索引。

用列表推导式来取代map 和filter

不要使用含有两个以上表达式的列表推导

用生成器表达书来改写数据量较大的列表推导

  • 当输入的数据量较大时,列表推导可能会因为占用太多内存而出问题
  • 由生成器表达式所返回的迭代器,可以逐次产生输出值,从而避免了内存用量问题
  • 把某个生成器表达式所返回的迭代器,放在另一个生成器表达式的for子表达式中,即可将二者组合一起
  • 串在一起的生成器表达式执行速度很快

尽量用enumerate替代range

用zip函数同时遍历两个迭代器

合理利用try/except/else/finally结构中的每个代码块

  • 无论try块是否生成异常,都可利用try/finally复合语句中的finally块来执行清理工作
  • else块可以用来缩减try块中的代码量,并把没有发生异常时要执行的语句与try/except代码块隔开

函数

尽量用异常来表示特殊情况,而不要返回None

了解如何在闭包里使用外围作用域中的变量

def sort_priority(values, group):
    def helper(x):
        if x in group:
            return (0, x)
         return (1, x)
   values.sort(key=helper)
number = [8, 3, 1, 2, 5, 4, 7, 6]
group = {2, 3, 5, 7}
sort_priority(number, group)

考虑用生成器来改写直接返回列表的函数

在参数上面迭代时,要多加小心

用数量可变的位置参数减少视觉杂讯

*args, **kwargs,这一点也是我自己做的不够好

用关键字参数来表达可选的行为

用None和文档字串符来描述具有动态默认值的参数

用只能以关键字形式指定的参数来确保代码明晰

类与继承

尽量用辅助类来维护程序的状态,而不是用字典和元组

  • 不要使用包含其他字典的字典,也不要使用过长的元组。
  • 如果容器中包含简单而不可变的数据,那么可以先使用namedtuple来表示。
  • 保存内部状态的字段如果变得复杂,那就应该把这些代码拆解为多个辅助类

简单的接口应该接受函数,而不是类的实例

  • 对于链接各种Python组件的简单接口来说,通常应该给其直接传入函数,而不是先定义某个类,然后再传入类的实例。
  • Python中的函数和方法都可以像一级类那样引用,因此,它们与其他类型的对象一样,也能够放在表达式里面。

多用public属性,少用private属性

继承collections.abc以实现自定义的容器类型

以@classmethod形式的多态去通用地构建对象

  • 在Python程序中,每个类只能有一个构造器

元类及属性

用纯属性取代get和set方法

用@property来代替属性重构

用描述符来改写需要复用的@property方法

用元类来验证子类

并发与并行

考虑用协程来并发地运行多个函数

考虑用concurrent.futures来实现真正的平行计算

内置模块

用functools.wraps定义函数修饰器

Python用特殊的语法来表示修饰器,这些修饰器可以用来修饰函数。对于收到封装的原函数来说,修饰器能够在那个函数执行之前以及执行完毕之后,分别运行一些附加代码。这使得开发者可以在修饰器里面访问并修改原函数的参数及返回值,以实现约束语义、调试程序、注册函数等目标。

应该用datetime模块来处理本地时间,而不是用time模块

使用内置算法以及数据结构

  • 双向队列 collection.deque
  • 有序字典 collection.OrderedDict
  • 带有默认值的字典:collections.defaultdict
  • 堆队列(优先级队列)
  • 与迭代器相关的工具
    在这里插入图片描述

在重视精确度的场合,应该使用decimal

协作开发

为每个函数、类和模块编写文档字符串

用包来安排模块,并提供稳固的API

为自编的模块定义根异常,以便将调用者与API相隔离

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值