文章目录
Python代码规范整理
一、Python语言规范
1.1 Lint
对你的代码运行pylint
1.2 导入
仅对包和模块使用导入
1.3 包
使用模块的全路径名来导入每个模块
1.4 异常
允许使用异常, 但必须小心
定义:异常是一种跳出代码块的正常控制流来处理错误或者其它异常条件的方式.
1.5 全局变量
避免全局变量
1.6 嵌套/局部/内部类或函数
鼓励使用嵌套/本地/内部类或函数
定义:类可以定义在方法, 函数或者类中. 函数可以定义在方法或函数中. 封闭区间中定义的变量对嵌套函数是只读的.
1.7 列表推导
列表推导(list comprehensions)与生成器表达式(generator expression)提供了一种简洁高效的方式来创建列表和迭代器, 而不必借助map(), filter(), 或者lambda.
1.8 默认迭代器和操作符
如果类型支持, 就使用默认迭代器和操作符. 比如列表, 字典及文件等.
定义:容器类型, 像字典和列表, 定义了默认的迭代器和关系测试操作符(in和not in)。
1.9 生成器
按需使用生成器.
定义:所谓生成器函数, 就是每当它执行一次生成(yield)语句, 它就返回一个迭代器, 这个迭代器生成一个值. 生成值后, 生成器函数的运行状态将被挂起, 直到下一次生成.
1.10 Lambda函数
适用于单行函数
定义:与语句相反, lambda在一个表达式中定义匿名函数. 常用于为 map() 和 filter() 之类的高阶函数定义回调函数或者操作符.
1.11 条件表达式
适用于单行函数
定义:条件表达式是对于if语句的一种更为简短的句法规则. 例如: x = 1 if cond else 2 .
1.12 默认参数值
适用于大部分情况.
定义:你可以在函数参数列表的最后指定变量的值, 例如, def foo(a, b = 0): . 如果调用foo时只带一个参数, 则b被设为0. 如果带两个参数, 则b的值等于第二个参数.
1.13 属性(properties)
访问和设置数据成员时, 你通常会使用简单, 轻量级的访问和设置函数. 建议用属性(properties)来代替它们.
定义:一种用于包装方法调用的方式. 当运算量不大, 它是获取和设置属性(attribute)的标准方式.
1.14 True/False的求值
Python在布尔上下文中会将某些值求值为false. 按简单的直觉来讲, 就是所有的”空”值都被认为是false. 因此0, None, [], {}, “” 都被认为是false.
1.15 过时的语言特性
尽可能使用字符串方法取代字符串模块. 使用函数调用语法取代apply(). 使用列表推导, for循环取代filter(), map()以及reduce().
1.16 词法作用域(Lexical Scoping)
嵌套的Python函数可以引用外层函数中定义的变量, 但是不能够对它们赋值. 变量绑定的解析是使用词法作用域, 也就是基于静态的程序文本. 对一个块中的某个名称的任何赋值都会导致Python将对该名称的全部引用当做局部变量, 甚至是赋值前的处理. 如果碰到global声明, 该名称就会被视作全局变量.
1.17 函数与方法装饰器
用于函数及方法的装饰器 (也就是@标记). 最常见的装饰器是@classmethod 和@staticmethod, 用于将常规函数转换成类方法或静态方法. 不过, 装饰器语法也允许用户自定义装饰器.
1.18 不要依赖内建类型的原子性.
优先使用Queue模块的 Queue 数据类型作为线程间的数据通信方式. 另外, 使用threading模块及其锁原语(locking primitives). 了解条件变量的合适使用方式, 这样你就可以使用 threading.Condition 来取代低级别的锁了.
1.19 威力过大的特性
避免使用这些特性
Python是一种异常灵活的语言, 它为你提供了很多花哨的特性, 诸如元类(metaclasses), 字节码访问, 任意编译(on-the-fly compilation), 动态继承, 对象父类重定义(object reparenting), 导入黑客(import hacks), 反射, 系统内修改(modification of system internals), 等等.
二、Python风格规范
2.1 分号
不要在行尾加分号, 也不要用分号将两条命令放在同一行.
2.2 行长度
每行不超过80个字符
不要使用反斜杠连接行.
2.3 括号
宁缺毋滥的使用括号
2.4 缩进
用4个空格缩进
2.5 空行
顶级定义之间空两行, 方法定义之间空一行
2.6 空格
按照标准的排版规范来使用标点两边的空格
2.7 shebang
大部分.py文件不必以#!作为文件的开始. 根据 PEP-394 , 程序的main文件应该以 #!/usr/bin/python2或者 #!/usr/bin/python3开始.
2.8 注释
确保对模块, 函数, 方法和行内注释使用正确的风格
2.9 类
如果一个类不继承自其它类, 就显式的从object继承. 嵌套类也一样.
2.10 字符串
即使参数都是字符串, 使用%操作符或者格式化方法格式化字符串. 不过也不能一概而论, 你需要在+和%之间好好判定.
2.11 文件和sockets
在文件和sockets结束时, 显式的关闭它. 建议使用“with”
除文件外, sockets或其他类似文件的对象在没有必要的情况下打开, 会有许多副作用, 例如:
- 它们可能会消耗有限的系统资源, 如文件描述符. 如果这些资源在使用后没有及时归还系统, 那么用于处理这些对象的代码会将资源消耗殆尽.
- 持有文件将会阻止对于文件的其他诸如移动、删除之类的操作.
- 仅仅是从逻辑上关闭文件和sockets, 那么它们仍然可能会被其共享的程序在无意中进行读或者写操作. 只有当它们真正被关闭后, 对于它们尝试进行读或者写操作将会抛出异常, 并使得问题快速显现出来.
2.12 TODO注释
为临时代码使用TODO注释, 它是一种短期解决方案. 不算完美, 但够好了.
#TODO(Zeke) Change this to use relations.
2.13 导入格式
每个导入应该独占一行
2.14 语句
通常每个语句应该独占一行
2.15 访问控制
在Python中, 对于琐碎又不太重要的访问函数, 你应该直接使用公有变量来取代它们, 这样可以避免额外的函数调用开销. 当添加更多功能时, 你可以用属性(property)来保持语法的一致性.
2.16 命名
- 应该避免的名称
单字符名称, 除了计数器和迭代器.
包/模块名中的连字符(-)
双下划线开头并结尾的名称(Python保留, 例如__init__)
- 命名约定
所谓”内部(Internal)”表示仅模块内可用, 或者, 在类内是保护或私有的.
用单下划线(_)开头表示模块变量或函数是protected的(使用from module import *时不会包含).
用双下划线(__)开头的实例变量或方法表示类内私有.
将相关的类和顶级函数放在同一个模块里. 不像Java, 没必要限制一个类一个模块.
对类名使用大写字母开头的单词(如CapWords, 即Pascal风格), 但是模块名应该用小写加下划线的方式(如lower_with_under.py). 尽管已经有很多现存的模块使用类似于CapWords.py这样的命名, 但现在已经不鼓励这样做, 因为如果模块名碰巧和类名一致, 这会让人困扰.
- Python之父Guido推荐的规范
2.17 Main
即使是一个打算被用作脚本的文件, 也应该是可导入的. 并且简单的导入不应该导致这个脚本的主功能(main functionality)被执行, 这是一种副作用. 主功能应该放在一个main()函数中.
def main()
if name == “main”