python代码规范–如何写出优雅、简洁并易于理解的代码
首部信息
首先在创建文件时,应该在文件首部声明一些必要信息,如开发者姓名、开发者联系方式以及该脚本的功能描述等,这样便于后续脚本的维护和审查。
若使用pycharm
开发工具,可以在File-->settings-->Editor-->FIle and Code Templates
中设置,这样每次新建文件时会自动生成某些基础信息。
基础信息模板:
1 | # _*_ coding:utf-8 _*_ |
面向对象Class
- 类名使用驼峰式命名方法,类名应与脚本文件名一致
对于无须继承任何类(或者说继承于基类
object
)的类,使用classs ClassName:
而非class ClassName(object):
定义对于类变量或全局变量,使用全大写英文单词命名,多个单词间使用
_
连接,最多不超过3个ps
: 类变量指的是定义在类中,但在各个类方法外的变量。类变量的特点是:所有类的实例化对象都可以共享类变量的值,即类变量可以在所有实例化对象中作为公用资源。 类变量推荐直接用类名访问,但也可以使用对象名访问。使用全小写英文单词命名实例变量或普通变量,如果需要多个单词的,单词之间使用
_
连接,单个变量使用单词的个数不超过3个私有变量/保护变量:
_xxx
单下划线开头叫保护变量,意思是只有类对象和子类对象自己能访问到这些变量,此变量不能通过from XXX import xxx
导入;__xxx
双下划线开头叫私有变量,只允许类本身访问,连子类对象也不能访问到这个数据ps
:私有方法和保护方法的定义该规则同样适用使用
self
作为实例方法的第一个参数;使用cls
作为类方法的第一个参数;当定义的方法在实现时并不需要引用类或者实例时,定义为静态方法,使用 装饰器@staticmethod
来定义ps
:类方法较少使用,其具体使用场景有待总结
代码长度
一行代码最多不要超过79个字符
超出此限制时应该在元素周围使用()
包围并拆行,而不是在行末添加\
并换行
空行规定
- 文件头部的引用声明与正式代码之间有两个空行
- 类声明周围有两个空行
- 类外部的函数周围有两个空行
- 类外部的逻辑块,如条件、循环语句周围有两个空行
- 类内部方法声明周围有一个空行
- 类外部的变量周围有一个空行
- 文件末尾添加一个空行
导入规定
- 一行导入一个库里的文件,隶属于不同库的量不要在一行导入
- 引用按照内置、第三方、本地库的顺序排序,各类引用之间有一个空行。
缩进
使用四个空格作为缩进;使用Space
而不是Tab
键输入缩进。建议将编辑器设置为一个Tab表示4个空格,并配置按Tab时插入空格,vscode
按Ctrl
+ ,
。
容器类型书写规范
列表,字典,元组等,首末元素与对应的包围符号之间、函数调用的括号周围没有空格
容器类型尾元素最后没有“,
”,各元素之间的“,
”后面有一个空格
糟糕:
1 | bad_list = [ 1,2, ] |
优雅:
1 | good_list = [1, 2] |
符号及空格
逗号
,
之后要有一个空格,示例见上文字典的冒号之后有一个空格;列表切片的冒号之间没有空格
- 操作符,如
+
,-
,*
,/
,=
,==
,+=
周围有一个空格
函数规定
必须使用函数注解
函数注解的使用十分简单并且有利于所有人——包括自己对于程序的理解
示例
1 | from bs4 import BeautifulSoup |
函数文档字符串
对于简单函数,判断标准为参数少于等于三个,不需要;复杂函数需要使用文档字符串并包含以下内容
对于提供给所有人使用的公共方法,文档字符串中必须提供调用示例和返回值示例
- 函数的作用
- 各参数的作用及其限制
- 调用示例
函数默认参数的=
号周围没有空格
如果函数返回None
则无需指明返回值类型;函数末尾的return
语句,不需要
函数长度:如果一个函数一个屏幕放不下,建议拆分,这里没有固定长度,酌情而定,原则是一个函数不要过于复杂。
使用对象自身的真值
糟糕
1 | empty_list = [] |
优雅
1 | empty_list = [] |
语句使用规定
合理使用try
语句块。try
语句仅仅只用于可能抛出异常的语句,不要用其监控一大段代码,将正常执行的其它代码放在else
语句中
糟糕
1 | from json import loads |
优雅
1 | json_str = 'json字符串' |
使用continue
、break
等语句搭配提前返回
示例
1 | for each in range(10): |
异常的使用
记住几点基础的即可,个人自定的异常默认都继承于Exception
,异常只是一个名字,表示某种超出预期之外的情况
1 | BaseException |
- 使用
except Exception:
会捕获绝大部分自定义异常,但不能捕获Ctrl + C
触发的KeyboardInterrupt
异常 - 使用
except:
会捕获BaseException
,这会拦截掉所有异常,不要使用
常见异常
1 | ValueError: 如 int('hello') |
提前返回
提前返回是避免产生多层嵌套判断的重要技巧,主要方法就是不判断为真的条件而判断假的条件,满足假的情况下即返回
糟糕
1 | def process(condition: str): |
优雅
1 | def process(condition: str): |
_
变量名
_
代表程序中上句表达式的值,这通常是无用的
示例
1 | # 使用for循环控制重试次数 |
lambda匿名函数
基本语法: lambda argument_list: expression
这里的argument_list是参数列表,它的结构与Python中函数(function)的参数列表是一样的;
这里的expression是一个关于参数的表达式。表达式中出现的参数需要在argument_list中有定义,并且表达式只能是单行的。
下面是一些lambda函数示例:
1 | lambda x, y: x*y;函数输入是x和y,输出是它们的积x*y |
高阶函数
一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数
map函数: 接收的是两个参数,一个函数,一个序列(可迭代对象),其功能是将序列中的值处理再依次返回至列表内;其返回值为一个迭代器对象;为python内置函数;
示例:
1
2
3
4
5list(map(lambda x:x.upper(),"amanda"))
['A', 'M', 'A', 'N', 'D', 'A']
list(map(lambda x: x*x, range(10)))
[0, 1, 4, 9, 16, 25, 36, 49, 64,81]filter函数: filter函数也是接收一个函数和一个序列(可迭代对象),其主要功能是过滤。其返回值也是迭代器对象 ;为python内置函数;
示例:
1
2
3
4
5
6names=["Alex","amanda","xiaowu"]
list(filter(lambda x:x.islower(),names))
['amanda', 'xiaowu']
list(filter(lambda x: x > 2, range(10)))
[3, 4, 5, 6, 7, 8, 9]reduce函数: reduce函数也是一个参数为函数,一个为一个序列(可迭代对象),其返回值为一个值而不是迭代器对象,故其常用与叠加、叠乘等 ;非内置函数,在模块
functools
中,需要导入;示例:
1
2
3
4
5
6
7
8
9
10
11
12nums = [1, 2, 3, 4, 5, 6]
reduce(lambda x,y:x*y,nums)
720
reduce(lambda x,y:x*y,nums,100)
72000
reduce(lambda x,y:x+y,nums)
21
reduce(lambda x,y:x+y,nums,100)
121注:reduce还支持第三个参数,其作为叠加或叠乘的基数
sorted函数 :python内置排序函数,第一个参数为序列(可迭代对象),第二个参数为映射函数(可自定义),第三个可选参数为reverse(逆序);
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14sorted([36, 5, -12, 9, -21])
[-21, -12, 5, 9, 36]
sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]
sorted(['bob', 'about', 'Zoo', 'Credit'])
['Credit', 'Zoo', 'about', 'bob'] # 默认按ASCII值排序的
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower) # 不区分大小写
['about', 'bob', 'Credit', 'Zoo']
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
['Zoo', 'Credit', 'bob', 'about']any函数: any() 函数用于判断给定的可迭代参数
iterable
是否全部为 False,则返回 False,如果有一个为 True,则返回 True;python内置函数;示例:
1
2
3
4any([False, '', [], None, {}, (), 0])
False
any([False, '', [], None, {}, (), 1])
True注:仅支持一个参数
all函数: all() 函数用于判断给定的可迭代参数
iterable
中的所有元素是否都为 True,如果是返回 True,否则返回 False ;python内置函数;示例:
1
2
3
4
5all([False, '', [], None, {}, (), 1])
False
all([True, 'abc', ['1'], {'a': 'b'}, (1, 1), 1])
True