Python代码开发规范
1. 命名规范
1.1 命名规范表
Type | Public | Internal | Description |
---|---|---|---|
模块名 | lower_with_under | _lower_with_under | 模块是一种以.py为后缀的文件,模块尽量使用小写命名,首字母保持小写,尽量不要用下划线(除非多个单词,且数量不多的情况) |
包名 | lower_with_under | … | 包文件一般由_init_.py和其他诸多.py文件构成,包的命名尽量使用小写字母加下划线形式 |
类名 | CamelCase | _CamelCase | 类名使用驼峰命名风格,首字母大写,私有类可用一个下划线开头 |
异常命名 | CamelCase | … | 代码中的异常使用驼峰命名风格,每个单词首字母大写 |
函数 | lower_with_under() | _lower_with_under() | 函数名一律小写,如有多个单词,用下划线隔开,私有函数在函数前加一个下划线 |
全局/类 常量 | CAPS_WITH_UNDER | _CAPS_WITH_UNDER | 常量使用以下划线分隔的大写命名 |
全局/类 变量 | lower_with_under | lower_with_under | 变量名尽量小写, 如有多个单词,用下划线隔开 |
实例变量 | lower_with_under | _lower_with_under(protected) __lower_with_under (private) | 实例变量使用小写加下划线方式命名,protected类型在前面加一个下划线,private类型在前面加两个下划线 |
类方法 | lower_with_under() | _lower_with_under()(protected) __lower_with_under()(private) | 类方法一律小写,如有多个单词,用下划线隔开,protected类型在前面加一个下划线,private类型在前面加两个下划线 |
函数参数 | lower_with_under | … | 参数名一律使用小写加下划线形式 |
局部变量 | lower_with_under | … | 局部变量一律小写,如有多个单词,用下划线隔开 |
- 所谓”内部(Internal)“表示仅模块内可用,或者,在类内是保护或私有的;
- 用单下划线(_)开头表示模块变量或函数是protected的(使用import * from时不会包含);
- 用双下划线(__)开头的实例变量或方法表示类内私有。
1.2 命名约定
- 永远不要使用字母’l’(小写的L),‘O’(大写的O),或者’I’(大写的I)作为单字符变量名;
- 包/模块名中使用下划线(_)而不使用连字符(-)。
2. 代码规范
如无特殊情况,文件一律使用UTF-8编码,文件头部加入# -*- coding: utf-8 -*-标识
2.1 缩进
-
统一使用4个空格进行缩进(一般开发工具会自动完成缩进)
-
续行应该与其包裹元素对齐,要么使用圆括号、方括号和花括号内的隐式行连接来垂直对齐,要么使用挂行缩进对齐。当使用挂行缩进时,应该考虑到第一行不应该有参数,以及使用缩进以区分自己是续行
# 与左括号对齐 foo = long_function_name(var_one, var_two, var_three, var_four) # 挂行缩进应该再换一行 foo = long_function_name( var_one, var_two, var_three, var_four)
-
在多行结构中的大括号/中括号/小括号的右括号可以与多行结构的第一行第一个字符对齐
my_dict = { 'user': 'aaa', 'age': 25 } my_list = [ 1, 2, 3, 4, 5, 6 ] result = some_function_that_takes_arguments( 'a', 'b', 'c', 'd', 'e', 'f' )
2.2 行的长度
- 每行代码尽量不超过 80 个字符(在特殊情况下可以略微超过 80 ,但最长不得超过 120);
- 以下情况的行字符可超过80个:
- 长的导入模块语句
- 注释中的URL
2.3 换行
-
换行使用圆括号、中括号和花括号中的行隐式连接起来,不推荐使用反斜杠进行连接;
# 推荐写法 func(width, height, color, name, age, x, y) if (width == 0 and height == 0 and color == 'red' and emphasis == 'strong'): # 如果一个文本字符串在一行放不下, 可以使用圆括号来实现隐式行连接 x = ('这是一个非常长非常长非常长非常长 ' '非常长非常长非常长非常长非常长非常长的字符串') # 针对sql语句 # 推荐写法 agent_sql = ("CREATE TABLE IF NOT EXISTS db_agent (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "device_id VARCHAR(128) DEFAULT '', " "status INTEGER DEFAULT 1, " "updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, " "created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP)") # 不推荐 query_sql = "SELECT image_id, image_o, image_width, image_height "\ "FROM active_image_tbl "\ "WHERE auction_id=:auction_id AND status=1 " \ "ORDER BY image_id DESC"
-
推荐在二元运算符之后进行换行,提高代码的可读性
# 推荐:运算符和操作数很容易进行匹配 income = (gross_wages + taxable_interest + (dividends - qualified_dividends) - ira_deduction - student_loan_interest) # 不推荐: 操作符离操作数太远 income = (gross_wages + taxable_interest + (dividends - qualified_dividends) - ira_deduction - student_loan_interest)
-
禁止使用复合语句,即一行中包含多个语句;
# 推荐 func_a() func_b() func_c() # 不推荐 func_a(); func_b(); func_c();
-
if/for/while语句一定要换行。
# 推荐 if foo == 'blah': do_blah_thing() # 不推荐 if foo == 'blah': do_blah_thing()
2.4 引号
- 自然语言使用双引号"…",例如错误信息等;
- 机器标识使用单引号’…',例如字典里面的key等;
- 文档字符串使用三个双引号"“”…“”"
2.5 空行
-
顶层函数和类的定义,前后用两个空行分隔开;
-
类里面的方法定义用一个空行隔开;
class A: def __init__(self): pass def hello(self): pass def main(): pass
-
相关的功能组可以用额外的空行(谨慎使用)隔开;
-
在函数中使用空行来区分逻辑段(谨慎使用)。
2.6 表达式和语句中的空格
-
紧跟在小括号,中括号或者大括号后不要加空格
# 推荐 spam(ham[1], {eggs: 2}) # 不推荐 spam( ham[ 1 ], { eggs: 2 } )
-
不要在逗号,分号,冒号前面加空格,而应该在它们的后面加
# 推荐 if x == 4: print x, y x, y = y, x # 不推荐 if x == 4: print x , y x , y = y , x
-
在二元运算符两边加一个空格:赋值(=),增量赋值(+=,-=),比较(==,<,>,!=,<>,<=,>=,in,not,in,is,is not),布尔(and, or, not)。
-
如果使用具有不同优先级的运算符,请考虑在具有最低优先级的运算符周围添加空格。有时需要通过自己来判断;但是,不要使用一个以上的空格,并且在二元运算符的两边使用相同数量的空格。
# 推荐 i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (a-b) # 不推荐 i=i+1 submitted +=1 x = x * 2 - 1 hypot2 = x * x + y * y c = (a + b) * (a - b)
-
当’=’用于指示关键字参数或默认参数值时,不加空格,且函数不同参数之间逗号后面加空格
# 推荐 def complex(real, imag=0.0): return magic(r=real, i=imag) # 不推荐 def complex(real, imag = 0.0): return magic(r = real, i = imag)
-
不要用空格来垂直对齐多行间的标记
# 推荐 x = 1 y = 2 long_variable = 3 # 不推荐 x = 1 y = 2 long_variable = 3
2.7 import导入格式
-
导入总是位于文件的顶部,在模块注释和文档字符串之后,在模块的全局变量与常量之前
-
导入应该按照以下顺序分组:
- 标准库导入
- 相关第三方库导入
- 本地应用/库特定导入
-
导入库的一些初始化操作,需要放到全部库导入完毕后
# 推荐 import os import sys import warnings import pandas as pd import pymysql from sklearn.metrics import accuracy_score, roc_auc_score warnings.filterwarnings("ignore") pymysql.install_as_MySQLdb() # 不推荐 import os, sys import warnings warnings.filterwarnings("ignore") import pandas as pd import pymysql pymysql.install_as_MySQLdb() from sklearn.metrics import accuracy_score, roc_auc_score
2.8 模块级的”呆“名
-
所谓模块级的”呆“名指的是名字里有两个前缀下划线和两个后缀下划线,应该放在文档字符串的后面,以及除from _future_ 之外的import表达式前面。
"""This is the example module. This module does stuff. """ from __future__ import barry_as_FLUFL __all__ = ['a', 'b', 'c'] __version__ = '0.1' __author__ = 'Cardinal Biggles' import os import sys
2.9 异常
-
try后面放置可能会引发异常的代码块;
-
except后面需要指定捕捉的异常,捕捉所有异常,意味着会隐藏潜在的问题,可以有多个 except 语句,捕捉多种异常,分别做异常处理;
-
else为程序不出现异常时需要处理的代码;
-
finally主要用于回收程序资源。
try: #业务实现代码 ... except SubException as e: #异常处理块1 ... except SubException2 as e: #异常处理块2 ... else: #正常处理块 ... finally: #资源回收块 ...
3. 注释
3.1 块注释
-
块注释通常缩进到与代码相同的级别,每一行开头使用一个#和一个空格,块注释内部的段落通过只有一个#的空行分隔
# 块注释 # 块注释 # # 块注释 # 块注释
3.2 行注释
-
行内注释和代码至少要有两个空格分隔。注释由#和一个空格开始。避免无意义的注释
# 推荐 x = x + 1 # 边框加粗一个像素 # 不推荐 x = x + 1 # x增加1
3.3 特殊注释
-
比较重要的注释段, 使用多个等号隔开, 可以更加醒目, 突出重要性
app = create_app(name, options) # ===================================== # 请勿在此处添加 get post等app路由行为 !!! # ===================================== if __name__ == '__main__': app.run()
3.4 文档字符串(docstrings)
作为文档的docstrings一般出现在模块头部、函数和类的头部,这样在python中可以通过对象的__doc__对象获取文档。
-
函数和方法:文档字符串应该包含函数做什么, 以及输入和输出的详细描述。文档字符串应该提供足够的信息, 当别人编写代码调用该函数时, 他不需要看一行代码, 只要看文档字符串就可以。
def func(arg1, arg2): """这里一句话概括该函数方法的功能作用 函数的具体描述 :param arg1: 参数一的描述说明 :param arg2: 参数二的描述说明 :return: 说明函数返回的内容 example:: >>> a, b = 1, 2 >>> print(func(a, b)) """ pass
-
类:其定义下有一个用于描述该类的文档字符串
class SampleClass(object): """这里一句话概述该类的内容 类的具体描述 Attributes: attr1: 属性一的描述说明 attr2: 属性二的描述说明 example:: >>> a, b = 1, 2 >>> sc = SampleClass(a, b) """ def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2
3.5 TODO注释
-
TODO注释应该在所有开头处包含"TODO"字符串,紧跟着是用括号括起来的你的名字,email地址或其它标识符。然后是一个可选的冒号。 接着必须有一行注释,解释要做什么。
# TODO(kl@gmail.com): Use a "*" here for string repetition.
3.6 模块注释
每个模块注释都应该包含下列项,依次是:
- 版权声明;
- 模块注释内容,包括模块陈述、模块中的类和方法的描述、版本及维护信息等;
- 作者声明,标识文件的原作者;
# Copyright (C), 2010-2013, China Standard Software Co., Ltd.
"""
FileName: Test.py
Author: Tony
Version: 0.1
Date: 2022-07-04
Description: 用一行文字概括模块或脚本,句号结尾。
Class Foo: 一行概述该模块中的类的用途。
function Bar(): 一行概述该模块中的函数的用途。
History: /* 历史修改记录 */
<Author> <Date> <Version> <Desc>
Tony 2022-07-04 0.1 Release
"""
__authors__ = [
'"Tony" <johnsmith@example.com>',
'"Jobe" <joeisgone@example.com>'
]
以上就是自己本人在平时的python代码开发过程中会注意的一些规范,大家可以根据自身的习惯进行简化,虽然会比较复杂,但是对于代码后续的条理性和可读性还是有很大帮助的,大家如果有自己平时觉得比较好的代码开发习惯,欢迎大家可以在评论区留下您的秘密武器!!!