首页 存档 技术 查看内容

Google Python 编程风格指南(一)  Python 风格指南 - 内容目录

2018-3-30 13:00 |来自: 互联网 504 0

摘要:  Python 风格指南 - 内容目录 背景 Python语言规范 Lint 导入 包 异常 全局变量 嵌套/局部/内部类或函数 列表推导(List Comprehensions) 默认迭代器和操作符 生成器 Lambda函数 条件表达式 默认参数值 属性(prope ...

 Python 风格指南 - 内容目录

  • 背景

  • Python语言规范

    • Lint

    • 导入

    • 异常

    • 全局变量

    • 嵌套/局部/内部类或函数

    • 列表推导(List Comprehensions)

    • 默认迭代器和操作符

    • 生成器

    • Lambda函数

    • 条件表达式

    • 默认参数值

    • 属性(properties)

    • True/False的求值

    • 过时的语言特性

    • 词法作用域(Lexical Scoping)

    • 函数与方法装饰器

    • 线程

    • 威力过大的特性

  • Python风格规范

    • 分号

    • 行长度

    • 括号

    • 缩进

    • 空行

    • 空格

    • Shebang

    • 注释

    • 字符串

    • 文件和sockets

    • TODO注释

    • 导入格式

    • 语句

    • 访问控制

    • 命名

    • Main




 背景

  Python 是 Google主要的脚本语言。这本风格指南主要包含的是针对python的编程准则。

  为帮助读者能够将代码准确格式化,我们提供了针对Vim的配置文件。对于Emacs用户,保持默认设置即可。

 Python语言规范

  Lint

  对你的代码运行pylint

  定义:

  pylint是一个在Python源代码中查找bug的工具. 对于C和C 这样的不那么动态的(译者注: 原文是less dynamic)语言, 这些bug通常由编译器来捕获. 由于Python的动态特性, 有些警告可能不对. 不过伪告警应该很少.

  优点:

  可以捕获容易忽视的错误, 例如输入错误, 使用未赋值的变量等.

  缺点:

  pylint不完美. 要利用其优势, 我们有时侯需要: a) 围绕着它来写代码 b) 抑制其告警 c) 改进它, 或者d) 忽略它.

  结论:

  确保对你的代码运行pylint.抑制不准确的警告,以便能够将其他警告暴露出来。

  你可以通过设置一个行注释来抑制告警. 例如:

dict = 'something awful' # Bad Idea... pylint: disable=redefined-builtin

  pylint警告是以一个数字编号(如C0112)和一个符号名(如empty-docstring)来标识的. 在编写新代码或更新已有代码时对告警进行医治, 推荐使用符号名来标识.

  如果警告的符号名不够见名知意,那么请对其增加一个详细解释。

  采用这种抑制方式的好处是我们可以轻松查找抑制并回顾它们.

  你可以使用命令pylint--list-msgs来获取pylint告警列表. 你可以使用命令pylint--help-msg=C6409, 以获取关于特定消息的更多信息.

  相比较于之前使用的pylint:disable-msg, 本文推荐使用pylint:disable.

  要抑制”参数未使用”告警, 你可以用”_”作为参数标识符, 或者在参数名前加”unused_”. 遇到不能改变参数名的情况, 你可以通过在函数开头”提到”它们来消除告警. 例如:

def foo(a, unused_b, unused_c, d=None, e=None):
  _ = d, e
  return a

  导入

  仅对包和模块使用导入

  定义:

  模块间共享代码的重用机制.

  优点:

  命名空间管理约定十分简单. 每个标识符的源都用一种一致的方式指示. x.Obj表示Obj对象定义在模块x中.

  缺点:

  模块名仍可能冲突. 有些模块名太长, 不太方便.

  结论:

  使用importx来导入包和模块.使用fromximporty, 其中x是包前缀, y是不带前缀的模块名.使用fromximportyasz, 如果两个要导入的模块都叫做y或者y太长了.例如, 模块sound.effects.echo可以用如下方式导入:

from sound.effects import echo
...
echo.EchoFilter(input, output, delay=0.7, atten=4)

  导入时不要使用相对名称. 即使模块在同一个包中, 也要使用完整包名. 这能帮助你避免无意间导入一个包两次.

  包

  使用模块的全路径名来导入每个模块

  优点:

  避免模块名冲突. 查找包更容易.

  缺点:

  部署代码变难, 因为你必须复制包层次.

  结论:

  所有的新代码都应该用完整包名来导入每个模块.应该像下面这样导入:

# Reference in code with complete name.
import sound.effects.echo

# Reference in code with just module name (preferred).
from sound.effects import echo

  异常

  允许使用异常, 但必须小心

  定义:

  异常是一种跳出代码块的正常控制流来处理错误或者其它异常条件的方式.

  优点:

  正常操作代码的控制流不会和错误处理代码混在一起. 当某种条件发生时, 它也允许控制流跳过多个框架. 例如, 一步跳出N个嵌套的函数, 而不必继续执行错误的代码.

  缺点:

  可能会导致让人困惑的控制流. 调用库时容易错过错误情况.

  结论:

  异常必须遵守特定条件:

  1. 像这样触发异常:raiseMyException("Errormessage")或者raiseMyException. 不要使用两个参数的形式(raiseMyException,"Errormessage")或者过时的字符串异常(raise"Errormessage").

  2. 模块或包应该定义自己的特定域的异常基类, 这个基类应该从内建的Exception类继承. 模块的异常基类应该叫做”Error”.

    class Error(Exception):
      pass
  3. 永远不要使用except:语句来捕获所有异常, 也不要捕获Exception或者StandardError, 除非你打算重新触发该异常, 或者你已经在当前线程的最外层(记得还是要打印一条错误消息). 在异常这方面, Python非常宽容,except:真的会捕获包括Python语法错误在内的任何错误. 使用except:很容易隐藏真正的bug.

  4. 尽量减少try/except块中的代码量. try块的体积越大, 期望之外的异常就越容易被触发. 这种情况下, try/except块将隐藏真正的错误.

  5. 使用finally子句来执行那些无论try块中有没有异常都应该被执行的代码. 这对于清理资源常常很有用, 例如关闭文件.

  6. 当捕获异常时, 使用as而不要用逗号. 例如

    try:
      raise Error
    except Error as error:
      pass

  全局变量

  避免全局变量

  定义:

  定义在模块级的变量.

  优点:

  偶尔有用.

  缺点:

  导入时可能改变模块行为, 因为导入模块时会对模块级变量赋值.

  结论:

  避免使用全局变量, 用类变量来代替. 但也有一些例外:

  1. 脚本的默认选项.

  2. 模块级常量. 例如: PI = 3.14159. 常量应该全大写, 用下划线连接.

  3. 有时候用全局变量来缓存值或者作为函数返回值很有用.

  4. 如果需要, 全局变量应该仅在模块内部可用, 并通过模块级的公共函数来访问.

  嵌套/局部/内部类或函数

  鼓励使用嵌套/本地/内部类或函数

  定义:

  类可以定义在方法, 函数或者类中. 函数可以定义在方法或函数中. 封闭区间中定义的变量对嵌套函数是只读的.

  优点:

  允许定义仅用于有效范围的工具类和函数.

  缺点:

  嵌套类或局部类的实例不能序列化(pickled).

  结论:

  推荐使用.

  列表推导(List Comprehensions)

  可以在简单情况下使用

  定义:

  列表推导(list comprehensions)与生成器表达式(generator expression)提供了一种简洁高效的方式来创建列表和迭代器, 而不必借助map(), filter(), 或者lambda.

  优点:

  简单的列表推导可以比其它的列表创建方法更加清晰简单. 生成器表达式可以十分高效, 因为它们避免了创建整个列表.

  缺点:

  复杂的列表推导或者生成器表达式可能难以阅读.

  结论:

  适用于简单情况. 每个部分应该单独置于一行: 映射表达式, for语句, 过滤器表达式. 禁止多重for语句或过滤器表达式. 复杂情况下还是使用循环.

Yes:
 result = []
 for x in range(10):
   for y in range(5):
     if x * y
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部