记录一下自己的代码规范以供随时查看,也给看到的网友一个参考,如有不足之处,欢迎批评讨论。代码规范主要参考了PEP 8 – Python代码风格指导、谷歌Python风格指导和PyCharm默认代码风格,也有一些自己的微小改动(若有会指出)和补充的地方。
目录
代码布局
缩进
每一级缩进使用4个空格,但考虑到每次缩进都要按四次空格太麻烦了,所以本人还是使用Tab键缩进,但要在IDE中检查是否将缩进指定为4个空格:
续行时如果括号前的内容较短则采用隐式续行,即元素垂直对齐于圆括号、方括号或花括号;如果括号前的内容较长则采用悬挂缩进,即在续行中再缩进一级即可,无须对齐括号,同时第一行不应该包含参数:
# 隐式续行,第二行同开始分界符(左括号)对齐
foo = function_name(var_one, var_two,
var_three, var_four)
# 悬挂缩进,续行多缩进一级以同其他代码区别,同时首行不包含参数
def long_long_long_long_long_long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
当if语句的条件部分长到需要换行写的时候,续行额外增加一级缩进:
# 在if语句的续行中额外增加一级缩进以区分判断和执行
if (this_is_one_thing and
that_is_another_thing):
do_something()
多行结束的右括号可以为了美观单独写一行,和首行第一个字符对齐:
my_list = [
1, 2, 3,
4, 5, 6,
]
每行最大长度
PEP8推荐每行代码的最大字符数限制为79,文档或注释则限制为72,以方便分屏查看代码。但实际使用时单行代码很容易超过该限制,尤其是代码逻辑层数较多、前面有大段缩进时,此时频繁强制换行容易降低代码可读性:
故本人建议将最大字符数限制为120(ps:120不够用,现在设成了140),方法如下:
1.取消勾选使用Black格式化程序;2.将强制换行位置修改为120并点击应用。
单行代码超过最大字符数限制的解决方法:将表达式用小括号括起来再用隐式续行,无法使用小括号的情况下用反斜杠续行:
# 使用小括号和隐式续行
result = (long_expression
+ another_long_expression)
# 使用反斜杠续行
with open('/path/to/some/file/you/want/to/read') as file_1, \
open('/path/to/some/file/being/written', 'w') as file_2:
file_2.write(file_1.read())
表达式换行在二元运算符之前换,以使运算符更贴近操作数:
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
空行
顶层函数和类的定义用两个空行隔开。类中的方法定义用一个空行隔开,可以使用额外的空行(尽量少)来分隔相关的函数组。在一组相关的、仅占一行的函数之间,可以不空行。可以在函数内使用空行(尽量少)区分逻辑段。
# 顶层函数和类的定义用两个空行隔开。
# 可以在函数内使用空行(尽量少)区分逻辑段。
def top_level_function():
# 第一段逻辑
do_something()
do_something_else()
# 第二段逻辑
do_something_more()
do_something_else_more()
# 类中的方法定义用一个空行隔开,可以使用额外的空行(尽量少)来分隔相关的函数组。
# 在一组相关的、仅占一行的函数之间,可以不空行。
class MyClass:
def method_one(self):
pass
def method_two(self):
pass
def method_a(self):pass
def method_b(self):pass
def method_c(self):pass
源文件编码
PEP8推荐代码和注释中尽量只使用ASCII编码,但考虑到对中文字符的使用需求,本人遵循的原则是:在代码中所有标识符只使用ASCII编码,但字符串文字和注释可以使用非ASCII编码。
# 正确示例:标识符只使用ASCII编码,字符串文字和注释可以使用非ASCII编码
result = 'ASCII string ' + '非ASCII字符串' # 注释
# 错误示例:标识符使用非ASCII编码
结果 = 'ASCII string ' + '非ASCII字符串'
模块引用
import应该写在代码文件的开头,位于模块注释和文档字符串之后,模块全局变量和常量声明之前。引用不同的模块要分行写,但引用同一个模块下的不同内容可以写在一行。import应该按以下顺序分组写:1.标准库;2.第三方库;3.本地库。不同组之间用空行隔开。
引用范围应该尽量小,在不啰嗦的情况下尽量用from <module> import代替import <module>,没有特殊原因不使用通配符import(from <module> import *)。
模块中的双下划线变量(变量名以两个下划线开头,两个下划线结尾),比如__all__,__author,__version__等,应该写在文档字符串之后,除form __future__ imports的任何其它类型的引用语句之前。
"""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
from subprocess import Popen, PIPE
from pandas import DataFrame, Series
from my_module import some_function
字符串引用
正常情况下只使用单引号表示字符串,但当字符串中包含单引号时,则采用双引号来表示字符串。用三个双引号使用三引号。
# 正常情况下只使用单引号表示字符串
name = 'Alice'
# 当字符串中包含单引号时,则采用双引号来表示字符串
message = "Don't worry, be happy!"
# 用三个双引号使用三引号
docstring = """This is a multi-line string.
It can span multiple lines and contain "double quotes"."""
表达式和语句中的空格
添加空格的规则太麻烦了,建议在编写代码时统一不加空格,编写完成后使用“重新格式化代码”功能自动添加空格。
末尾添加逗号
在定义单元素元组时末尾必须加逗号,其他情况下尽量不在末尾加逗号,除非是为将来有可能的扩展预留冗余。
#定义单元素元组时末尾必须加逗号
FILE = ('setup.cfg',)
#为将来有可能的扩展预留冗余的逗号
FILES = [
'setup.cfg',
'tox.ini',
]
initialize(FILES,
error=True,
)
注释
注释以#和一个空格开头,应该是完整的多个句子,并且以句号结尾。如果注释很短句号可以忽略。块注释写在对应代码之前,并且和对应代码有同样的缩进级别。尽量少用行内注释,如果用注释和代码语句之间有两个空格的间隔。
# 短注释
if condition:
# 这是一个块注释。
# 包含了多行文字。
x = x + 1 # 边界补偿
文档字符串
所有的公共模块,函数,类和方法都应该有文档字符串,该字符串位于声明的下一行,并且以单行"""结尾。
def my_function():
"""文档字符串在声明的下一行,并且以单行三引号结尾。
"""
命名约定
首要原则:用户可见的公共部分API,其命名应当表达出功能用途而不是具体的实现细节。
命名风格
命名使用带下划线小写的风格:lower_case_with_underscores。
以下划线开始或结尾的特殊形式有特定功能:
_single_leading_underscore: 以单个下划线开头是”内部使用”的弱标志。
single_trailing_underscore_: 以单个下划线结尾用来避免和Python关键词产生冲突。
__double_leading_underscore: 以双下划线开头的风格命名类属性表示触发命名修饰。
__double_leading_and_trailing_underscore__: 以双下划线开头和结尾的命名风格表示“魔术”对象或属性,用于重写以实现特定功能。
命名约定
全小写带下划线:模块名,函数名,变量名
全小写不带下划线:包名
驼峰命名法:类名(异常名若要抛出错误应加上Error后缀),类型变量名
全大写带下划线:常量名
禁止使用:单个字符’l’(L的小写的字母),’O’(o大写的字母),’I’(i的大写的字母)。
编程建议
代码应该以不影响其他Python实现(PyPy,Jython,IronPython,Cython,Psyco等)的方式编写。
None应该用is或is not作比较,不要使用==操作符。
用is not操作符而不是not ... is。
用富比较实现排序操作的时候,最好实现所有六个比较操作符( __eq__ 、 __ne__ 、 __lt__ , __le__ , __gt__ , __ge__),而不是依靠其他代码来进行特定比较。为了最大限度减少工作量,functools.total_ordering()装饰器提供了一个工具去生成缺少的比较方法。
不要通过赋值语句将lambda表达式绑定到一个变量上来定义函数。
异常类应派生自Exception而不是BaseException。
捕获异常时,尽可能使用明确的异常,而不是用一个空的except:语句。
对于所有try / except子句,将try子句限制为必需的绝对最小代码量,以避免屏蔽错误。
当某个资源仅被特定代码段使用时,用with语句确保其在使用后立即释放资源。
在函数中默认返回None的位置显式地指出return None。
用字符串方法代替字符串模块。
不要让字符串对尾随的空格有依赖。
不要用==比较True和False。