很多语言都有自己独有的编码风格python以简洁优美著称,当然也不能例外如果和本文规则发生任何冲突,请优先与项目级别的代码风格保持一致代码风格一致性当然重偠,想象一下空姐的制服诱惑是不是赏心悦目呢?但也要有自己的主观判断不墨守陈规,愚蠢的追求代码一致性例如有以下的场景:
1、遵循此风格写的一小片代码看起来和项目内其他代码格格不入,看到就想抠出来喂猪人人见而曰日之。
2、遵循此风格后和其他 python 版本鈈兼容甚至出现错误,这就尴尬了
3、遵循此风格中的某些条目使代码更不易读,简单说就是丑
1. 连续行使用两种方式使封装元素成为┅行:括号内垂直隐式连接 & 悬挂式缩进。 使用悬挂式缩进应该注意第一行不应该有参数连续行要使用进一步的缩进来区分。
# 括号内隐式連接垂直对齐 # 悬挂缩进,一般是四个空格但非必须 # 括号内隐式连接,没有垂直对齐时第一行的参数被禁止
3.4 代码行最大长度
将所有行限制为最多79个字符。对于具有较少结构限制(文档字符串或注释)的长文本块行长度应限制为72个字符。当然了不要问为啥非得是 7972。因為要兼顾非洲大陆人民的生活代码是全世界的。反斜杠有时可能仍然要用 例如,又多又长的 with - 语句不能使用隐式连接这时反斜杠是可鉯接受的:
3.5 运算符前还是后断行?
模块导入总是位于文件顶部,在模块注释和文档字符串之后模块全局变量和常量之前。
导入应该按照以丅顺序分组不同组间用空行隔离。
必须在除了 docstrings 之外的任何其他代码之前出现在模块中
在 Python 中,单引号和双引号是等价的只需要坚持使鼡一种并保持一致即可。
在双引号中使用单引号单引号中使用双引号。三引号中使用双引号
单元素元组强制使用逗号:
当使用版本控淛系统时,一组希望后续扩展的值/参数/改善的条目使用以下形式:
同等级别的一块代码的注释块注释内每行注释以 # 开头,内部注释段落の间使用以 # 开头的空行注释隔开
行注释和代码声明间至少间隔两个空格,不要使用无聊的行注释例如:
为所有公共模块,函数类和方法编写文档字符串。 对于非公共方法文本字符串不是必需的,但应该有一个描述该方法的注释例如:
6.1 描述性: 命名风格
6.2 规定性: 命名习慣
模块应该使用简短并且全小写的命名,下划线也可以使用以提升可读性
函数的命名习惯,可以通过 dir(__builtins__) 查看系统函数命名样例注意区分普通命名,异常名命名和 builtin 常量
异常应该是类,所以可以使用类命名习惯但是,如果异常是个错误类一般加上 "Error" 后缀。
我们假设这些全局变量只在一个模块内使用这样的话和函数的命名习惯是一样的。设计为通过 from M import * 导入的类应该使用 __all__ 机制避免导出全局变量或者可以使用咾式的习惯,给这些全局变量名加上下划线作为前缀(表示这是非公有变量)
6.2.8 函数和方法参数
如果函数入参名和保留关键字冲突,则后缀下劃线好过缩写或者糟糕的拼写例如,class_ 好过 clss
6.2.9 方法名和实例变量
使用函数命名风格即可。如果希望是私有方法或实例变量则前缀下划线。为避免和子类的命名冲突请使用双下划线前缀命名。如果类 Foo 有一个属性变量 __a那么通过 Foo.__a 是不能被访问的。当然固执的用户仍然可以通过 Foo._Foo__a
访问),一般来说双下划线前缀只是在避免子类属性命名冲突的场景下使用。
经常去思考类方法和实例变量(属性)应该是公有的還是非公有的(严格意义上python 没有私有变量)。如果不确定那就设置成非公有的。另一类属性类别是子类 API 的一部分(在其他语言中称"protected")。有些类天生就是被设计为用来继承的当设计这种类时,注意哪些属性是公有的哪些是子类 API
的一部分,哪些是只在基类中使用的
來自仁慈的python之父的指导:
- 公有实例变量不应该有前缀下划线。
- 公有实例变量和保留关键字冲突时变量名加前缀下划线避免,这比使用缩寫和其他糟糕的拼写要好(除了 'cls'当一个变量或入参确定是一个类,特别是作为类方法的第一个入参时'cls' 更惹人喜爱)。
- 对于简单的公有數据属性不要使用复杂的存取函数,直接暴露属性名
- 如果设计继承基类时,不希望子类访问的属性加双下划线前缀
文档说明的接口┅般认为是公共接口,除非文档明确声明为临时或内部接口(为了兼容性等其他原因)所有非文档说明的接口一般为内部接口。模块应該使用 __all__ 属性明确声明公共 API 名如果 __all__ 为空,则表明模块没有公共 API尽管使用了 __all__ 属性,内部接口(packages,
modules, classes, functions, attributes or other names)仍然需要使用前缀下划线如果包含的任哬一个命名空间(package, module or class)是内部的,那么这个接口也被认为是内部接口导入名应该总是被视为实现细节。其他导入模块一定不能依赖对此导叺名的间接访问除非它们是包含模块 API
的显式文档说明的部分,例如os.path 或者一个 package 向子模块暴露函数的 __init__ 模块
- 代码不应该以一种不利于其他 python 实現(PyPy, Jython, IronPython, Cython, Psyco 诸如此类)的方式编写。 例如:不要使用 a += b 或 a = a + b 来实现就地字符串连接在库的性能敏感部分,应该使用 ''.join() 的形式这就能保证在不同的 python 实現中,连接动作可以在线性时间内完成
- 尽管功能相同,从可读性上考虑:
- 使用 def 语句而不要使用赋值语句去直接绑定一个 lambda 表达式到标识符仩:
- 赋值语句的使用消除了 lambda 表达式相对于显式 def 语句的唯一好处那就是它能够嵌入到一个更大的表达式里面。
- 捕获的异常要说明 "错误出在哪里了 " 而不是仅仅说明 "哎呀!出问题了!"。
- 正确使用异常链接在 Python 3 中,应该使用 "raise X from Y" 来表示显式替换并且不会丢失原始追溯
- 当捕获异常时,尽可能提及具体的异常而不是使用一个赤裸裸的 except 子句一个裸露的 except: 子句将捕获 SystemExit 和 KeyboardInterrupt 异常,这样的话就难于使用 control-c 中断程序并可能掩盖其他問题。如果想要捕获标志程序错误的所有异常的话用 except Exception:(裸露的 except 子句等同于 except
- 当对捕获的异常重命名时,使用 2.6 版本引入的语法:
- 当捕获操作系統错误时相对于内置的 errno 值,最好是使用 Python 3.3 中介绍的显式异常层次结构
- 对于所有的 try/except 子句,将 try 子句限制为必需的绝对最小代码量避免隐藏 bug:
- 特定代码块的本地资源使用 with 语句确保使用后立即释放不能自动释放的使用 try/finally 也可以。
- 除了申请和释放资源任何时候都应该使用单独的函數和方法调用 Context managers,例如:
- 函数返回语句要一致在一个函数内的所有返回语句要么都返回一个表达式,要么都不返回如果任何一个返回语呴返回了表达式,那么其他任何没有返回值的语句应该明确声明为 return None在函数结束部分必须出现返回语句:
- 对象类型比较应该使用isinstance() 而不是直接比较:
- 当检查一个对象是否为字符串时,一定要注意这个对象也可能是 unicode 字符串!在Python 2 中string 和 unicode 拥有一个公共基类 basestring,因此可以这么的:
本文主要参考的是PEP8 Python编码规范和来源于互联网上圈子内的的优秀实践吸纳形成为我司的python编码规范攵档,计划将这套规范用于指导我司python编程者进行作业希望大家在日常的编码中都能遵守,拿它当作镜子时常照照,对提升自身技能也夶有裨益当然,对本规范有任何不尽人意的地方都可以联系我进行修正完善