************** python风格指南 ************** ==== 前言 ==== 本文包含代码风格、Python特性使用、面对不同问题的最佳解决方案三大块内容 代码风格是指编写代码过程当中的排版布局的问题,主要是PEP8当中的一些内容,针对PEP8我自己加了一些认为自己需要注意的点进去 Python特性使用是指对于写Python的过程当中 ======== 代码风格 ======== 空行 ---- 1. 模块顶级元素(类、函数)之间空两行 2. 类中的方法之间空一行 3. 其他认为有必要空行以分割逻辑块的地方空一行,不对对于逻辑快的区分优先使用函数解构的方法去做 导入 ---- 1. 引用层次依次为标准库的引用>第三方库的引用>项目内引用,不同引用层次之间空一行以表示区隔 2. 一般情况下不使用 ``from module import *`` 的写法 3. 仅在引用核心模块的时候使用 ``from module import something`` 的写法,对于非核心模块,均使用 ``import module`` 4. 可以在要引用的模块名过长的时候使用 ``import module as mod`` 这样的写法 缩进 ---- 1. 用四个空格来缩进代码 2. 优质的分行缩进方式范例 .. image:: _static/5A4787FE-BAF6-4E07-A355-5DC9361570C2.png 换行 ---- 1. 可以通过首个元素就换行来解决对齐问题 Shebang ------- Shebang亦即 ``#!`` ,只有被直接执行的文件才有必要加入 行长度 ------ 除了导入模块的语句,每行代码不超过80个字符 长表达式 -------- 1. 对于调用链使用如下的拆分方案 .. code-block:: python pagination = db.session.query(Vocabulary).\ filter_by(user_id=user_id, is_remember=False).\ paginate(page, per_page=20, error_out=False) 2. 对于多参数使用如下的拆分方案 .. code-block:: python new_word = Vocabulary( user_id=request_content['user_id'], word=request_content['word'], word_explain=request_content['explain'] ) 注释 ---- 1. 函数或方法的docstring 2. 类的docstring 3. 块注释 4. 行注释:不要使用行注释,全部用块注释代替,#后面要加空格 命名 ---- 1. 对于不希望外部使用的模块变量或函数使用单下划线(使用 ``import * from`` 的时候不会被包含) 2. 不要使用双下划线 3. 对于模块名使用小写加下划线的方式 Main ---- 所有的可执行代码都应该使用 ``if __name__=='__main__'`` 来包含可执行代码块,防止其被导入的时候产生副作用 引号 ---- 使用单引号而非双引号 ======== 功能使用 ======== 匿名函数 -------- 一般情况下,仅在参数需要可调用对象的时候使用使用匿名函数 在这种情况下,匿名函数的好处在于有些函数支持传入可调用对象,但不支持传入可调用对象的参数,这种方式可以解决这个问题 异常 ---- 1. 异常的触发必须使用这种形式: ``raise MyException("Error message")`` 或者 ``raise MyException`` 2. 模块和包定义自己的异常基类的时候应用从内建的Exception类继承(这个我暂时还用不上) 3. 如非必要,永远不要使用 ``except`` 或者 ``except Exception`` 这种来捕获所有的异常,前者比后者更加难以容忍,甚至会捕获KeyboardInterrupt 4. try块中的语句要尽量小,只包含你想要捕获异常的语句 5. 使用finally子句来执行哪些无论try快中有没有异常都应该被执行的代码 6. 异常的使用规范 .. image:: _static/93BBEB2A-D51E-40CC-AED0-8443807DAC56.png 我选择前者,更多使用异常处理而非条件判断 全局变量 -------- 避免使用全局变量,用类变量来代替除非在以下情况下: 1. 模块级常量 列表推导 -------- 1. 使用列表推导以代替map()和filter() 2. 不要滥用列表推导,列表推掉的使用前提是使代码显得清晰明确,如果有双重循环或者列表推导的长度过长,那么就不要去使用列表推导,而是应当直接使用循环 生成器 ------ 1. 对于要存储量大的数据,鼓励使用生成器(迭代器) 2. 生成器的意义在于其惰性产出值从而节省内存,如果一个生成器对象包含一个列表作为属性的话,那么就没有什么意义了 特性(properties) ---------------- 1. 使用 ``@property`` 装饰器来进行创建 2. 代替java当中那种烦人的get和set方法,维护接口的统一性 3. 可拓展性强,刚开始可以不使用特性,想用特性的时候又不会破坏原有的接口 函数参数 -------- 1. 尽量不要在参数列表中加复杂的对象(尽量只加基础对象) 2. 对于比较复杂的数据的情况,可以使用嵌套的元组、字典 3. 永远不要修改修改或保存传入的数据,对于可变对象而言,一定要复制一个副本,而非在元对象的基础上做改变 文件命名 -------- 1. python相关的文件统一使用下划线进行命名 2. ======== 最佳实践 ======== log --- 1. 日志的使用 .. image:: _static/BABE5B3A-2A49-4302-8DEF-24F4C2ED9408.png ==== 陷阱 ==== 使用可变对象作为默认参数值 -------------------------- 幽灵bus的阴影 用if去判断函数返回值是否为None ------------------------------ .. image:: _static/71455833-1590-4C6F-9AEF-A39DAF52D7C8.png