Python代码规约
Python之禅
import this
"""
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
"""
PEP
Python Enhancement Proposals,PEP,python完善提案
https://www.python.org/dev/peps/
https://www.cnblogs.com/abella/p/10056875.html
PEP的状态
每个PEP都有一个状态,用于指示它的生命周期阶段。一些常见的PEP状态包括:
- Draft:PEP正在进行初步讨论和草案编写。
- Accepted:PEP已被接受,但尚未实现。
- Final:PEP已经被实现并成为Python的一部分。
- Rejected:PEP被拒绝,通常伴随着拒绝的原因和讨论。
PEP的结构
PEP文档通常遵循特定的结构,包括标题、作者、提案摘要、动机、提案正文、实现细节、示例代码和参考文献等部分。熟悉PEP的结构可以帮助你更容易地理解其内容。
代码格式
基本风格
PEP8风格,PEP 8,Python Enhancement Proposal,Python增强指南,https://peps.python.org/pep-0008/,http://pep8.org/
https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python_style_rules/
https://pythonguidecn.readthedocs.io/zh/latest/writing/style.html
代码格式器
| 格式工具 | 格式风格 |
|---|---|
| Black | PEP8 |
| yapf | Google style |
| autopep8 | PEP8 |
导包规约
禁止使用
from xxx import *,应显示指明要导入的模块。from xxx import *会污染命名空间,被导入模块改动时可能会影响其他模块造成难以排查的问题。例外,在某些必须或惯用from xxx import *的场景下,必须使用__all__显示控制标识符的导出。import导入语句顺序,内置模块>三方模块或二方模块>一方模块,同级别遵循字典序。仅导入模块需要使用注释注明用途。
不使用直接导入模块内成员的方式,降低命名空间污染程度。
正例
import datetime print(datetime.datetime.now()) print(datetime.time())反例
若后续需要导入Python标准库
time就会导致问题。from datetime import time, datetime print(datetime.now()) print(time())例外
Python标准库
typing使用与该规约恰恰相反。from typing import Any, List, Dict一般项目中导包使用绝对导入方式,自定义库中使用相对导入方式。
命名规约
通用规则
避免使用中划线
-避免使用
__xxx__形式名称,该形式名称保留给Python解释器使用。尽量使用见名知意的命名。
PEP 8: E741 ambiguous variable name ‘l’
应避免使用字符I(i),O(O),L(l)来作为变量名,因为这些字符容易使人与数字1,0混淆
具体规则
| 标识符 | 公有 | 私有 |
|---|---|---|
| 包或模块名 | lower_case_and_underline | |
| 类名 | GreatHump | |
| 函数或方法名 | lower_case_and_underline | |
| 变量名(全局变量、局部变量、函数或方法参数) | lower_case_and_underline | |
| 常量名 | GREAT_HUMP_AND_UNDERLINE |
main规约
可执行Python脚本必须使用
if __name__ == '__main__'限制只有在顶层代码环境才可执行。禁止
if __name__ == '__main__下有复杂逻辑,应将逻辑交由main方法承载并作为可执行脚本入口函数。if __name__ == '__main__'及其下代码属于全局作用域,可能会掩盖一部分问题。正例
def main(): ... if __name__ == "__main__": main()反例
下方代码PyCharm不会检查出问题,但实际上,若某一个模块导入下方模块并调用函数
func会出现问题NameError: name 'a' is not defined。def func(): print(a) if __name__ == '__main__': a = 1
注释规约
非直观代码需要注释
正例
# 若i为2的任意次方 if i & (i - 1): ...反例
# 遍历items for i in itmes: ...代码更新时注释更新,具有误导性的错误注释比没有注释更糟糕
异常规约
- 自定义异常名以Error结尾,继承Exception
- 异常处理抛出异常实例
Exception('xxx')而非异常类本身Exception
语法规约
禁止使用嵌套的简化if语句,嵌套的简化if语句极大降低代码可读性。
正例
if age < 18: a = 0 else: a = 1 if age <= 60 else 2反例
a = 0 if age < 18 else 1 if age <= 60 else 2禁止使用可变对象作为函数或方法参数的默认值。函数参数默认值是函数的一部分,参数为可变类型会导致函数为有状态函数,造成潜在问题。
反例
def add_employee(names, emp_list=[]): for name in names: if check(name): emp_list.append(name) return emp_list print(add_employee(['张三', '李四'])) # ['张三', '李四'] print(add_employee(['王五', '赵六'])) # ['张三', '李四', '王五', '赵六']正例
def add_employee(names, emp_list=None): if emp_list is None: emp_list = [] for name in names: if check(name): emp_list.append(name) return emp_list print(add_employee(['张三', '李四'])) # ['张三', '李四'] print(add_employee(['王五', '赵六'])) # ['王五', '赵六']需要列表下标使用
enumerate正例
for idx, item in enumerate(lst): print(idx, item)反例
idx = 0 for i in lst: print(idx, i) idx += 1 for idx in range(len(lst)): print(idx, lst[idx])交换变量
正例
x, y = y, x反例
tmp = x x = y y = tmp字典默认值处理
反例
words, frequency = [(1, 'apple'), (2, 'banana'), (1, 'cat')], {} for freq, word in words: if freq not in frequency: frequency[freq] = [] frequency[freq].append(word)正例
words, frequency = [(1, 'apple'), (2, 'banana'), (1, 'cat')], {} for freq, word in words: frequency.setdefault(freq, []).append(word)from collections import defaultdict words, frequency = [(1, 'apple'), (2, 'banana'), (1, 'cat')], defaultdict(list) for freq, word in words: frequency[freq].append(word)善用key
d = {"张三": 14, "李四": 12, "王五": 13} print(max(d, key=d.get)) print(min(d, key=d.get)) print(sorted(d, key=d.get))
代码结构规约
- 将相互关联的类以及函数放在一个模块中,不需要限制一个模块只能有一个类。