Python PEP8 编码规范

2018-09-26  本文已影响0人  slords
PEP: 8
Title: Style Guide for Python Code
Version: c451868df657
Last-Modified: 2016-06-08 10:43:53 -0400 (Wed, 08 Jun 2016)
Author: Guido van Rossum <guido at python.org>, Barry Warsaw <barry at python.org>, Nick Coghlan <ncoghlan at gmail.com>
Status: Active
Type: Process
Content-Type: text/x-rst
Created: 05-Jul-2001
Post-History: 05-Jul-2001, 01-Aug-2013


Introduction 介绍

本文档提供了Python代码的编码约定,包括主Python发行版中的标准库。请参阅Python的C实现中描述C代码样式指南的配套信息PEP [1]

本文和PEP 257(Docstring约定)改编自Guido的原始Python风格指南文章,并附有Barry的风格指南[2]

随着时间的推移,随着语言本身的变化,过去的约定被淘汰,这种风格指南随着时间的推移而不断发展。

许多项目都有自己的编码风格指南。如果发生任何冲突,此类项目特定指南优先于该项目。

愚蠢的使用一致性是无知的怪物(A Foolish Consistency is the Hobgoblin of Little Minds)

Guido的一个重要观点,代码的读取频率远高于编写代码。此处提供的准则旨在提高代码的可读性,并使其在各种Python代码中保持一致。正如PEP 20所说,“可读性很重要”。

风格指南是关于一致性的。与此风格指南的一致性非常重要。项目内的一致性更为重要。一个模块或功能内的一致性是最重要的。

但是,知道何时不一致。有时风格指南建议不适用。如有疑问,请使用您的最佳判断。查看其他示例并确定最佳效果。并且不要犹豫,不要问!

特别是:不要为了遵守这个PEP而破坏向后兼容性!

忽略特定指南的其他一些好理由:

  1. 在应用指南时,即使是习惯于阅读此PEP之后的代码的人,也会使代码的可读性降低。
  2. 为了与周围的代码保持一致(也许是出于历史原因) - 虽然这也是一个清理别人的混乱的机会(真正的XP风格)。
  3. 因为有问题的代码早于指南的引入,所以没有其他理由可以修改该代码。
  4. 当代码需要与不支持样式指南推荐的功能的旧版Python兼容时。

代码布局

缩进

每个缩进级别使用4个空格。

Python可以使用包含在小括号,中括号和大括号内的方式使每行内容连续,或使用悬挂缩进,垂直对齐包装元素。使用悬挂缩进时,应考虑以下因素; 第一行应该没有参数,应该使用进一步的缩进来明确区分自己作为延续线。

悬挂缩进是一种类型设置样式,其中段落中的所有行都缩进,但第一行除外。在Python的上下文中,该术语用于描述一种样式,其中带括号的语句的左括号是该行的最后一个非空白字符,后续行缩进到右括号。

Yes:

# 与左括号对齐
foo = long_function_name(var_one,var_two,
                         var_three,var_four)

# 用更多的缩进来区分其他行
def long_function_name(
        var_one,var_two,var_three,
        var_four):
    print(var_one)

# 悬挂缩进应该增加一级
foo = long_function_name(
    var_one, var_two,
    var_three, var_four)

No:

# 有变量在第一行时禁止使用悬挂缩进
foo = long_function_name(var_one, var_two,
    var_three, var_four)

# 当缩进没有与其他行区分时,要增加缩进
def long_function_name(
    var_one, var_two, var_three,
    var_four):
    print(var_one)

四空格的规则对于续行是可选的。

Option:

# 悬挂缩进*可以*缩进量可以不是4个空格
foo = long_function_name(
  var_one, var_two,
  var_three, var_four)

当if语句的条件部分足够长以要求它跨多行写入时,值得注意的是两个字符关键字(即if)加上一个空格一个左括号的组合,创建了一个自然的多行条件的后续行的4空格缩进。这可能与嵌套在if语句中的缩进代码集产生视觉冲突,该代码集自然也会缩进到4个空格。该PEP没有明确地说明如何(或是否)进一步在视觉上将这些条件线与if语句内的嵌套套件区分开来。在这种情况下可接受的选择包括但不限于:

# 没有额外的缩进
if (this_is_one_thing and
    that_is_another_thing):
    do_something()

#添加注释,这将在编辑器中提供一些区别
#支持语法突出显示。
if (this_is_one_thing and
    that_is_another_thing):
    # Since both conditions are true, we can frobnicate.
    do_something()

#在条件连续行上添加一些额外的缩进。
if (this_is_one_thing
        and that_is_another_thing):
    do_something()

(另请参阅下面关于是否在二元运算符之前或之后中断的讨论。)

多行结构上的小括号/中括号/大括号可以在列表最后一行的第一个非空白字符下排列,如下所示:


my_list = [
    1, 2, 3,
    4, 5, 6,
    ]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
    )

或者它可以排在启动多行结构的行的第一个字符下面,如:

my_list = [
    1, 2, 3,
    4, 5, 6,
]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
)

制表符还是空格

空格是首选的缩进方法。
制表符应仅用于与已使用制表符缩进的代码保持一致。
Python 3不允许混合使用制表符和空格来缩进。
使用制表符和空格的混合缩进的Python 2代码应该转换为仅使用空格。
当使用-t选项调用Python 2命令行解释器时,它会发出有关非法混合制表符和空格的代码的警告。使用-tt时,这些警告会出错。强烈推荐这些选项!

每行最大字符数

将所有行限制为最多79个字符。

对于具有较少结构限制(文档字符串或注释)的长文本块,行长度应限制为72个字符。

限制所需的编辑器窗口宽度使得可以并排打开多个文件,并且在使用在相邻列中显示两个版本的代码审查工具时可以正常工作。

大多数工具中的默认包装会破坏代码的可视化结构,使其更难理解。选择限制是为了避免在窗口宽度设置为80的情况下包装在编辑器中,即使工具在包装线条时在最终列中放置标记字形。某些基于Web的工具可能根本不提供动态换行。

有些团队强烈倾向于更长的线路长度。对于专门或主要由可以就此问题达成一致的团队维护的代码,可以将标称行长度从80个字符增加到100个字符(有效地将最大长度增加到99个字符),前提是评论和文档字符串仍然包装72个字符。

Python标准库是保守的,需要将行限制为79个字符(文档字符串/注释限制为72个)。

包装长行的首选方法是在小括号,中括号和大括号内使用Python隐含的行继续。通过在括号中包装表达式,可以在多行上分割长行。这些应该优先于反斜杠的行继续。

反斜杠的行继续在以下情形适用。例如,long,多重with语句不能使用隐式延续,因此可以接受反斜杠:

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())

(请参阅前面关于多行if语句的讨论,以获得关于这种多重with语句缩进的进一步想法。)
另一种类似情况是使用assert语句。
确保在续行进行适当的缩进。

在二元运算符之前是否换行

几十年来,推荐的风格是在二元运算符之后打破。但这会以两种方式损害可读性:操作员倾向于分散在屏幕上的不同列上,并且每个操作符都会从其操作数移到前一行。在这里,眼睛必须做额外的工作来分辨哪些对象使用加法以及哪些对象使用减法:

# No: 对象远离操作符
income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)

为了解决这个可读性问题,数学家和他们的出版商遵循相反的惯例。Donald Knuth在他的《计算机和排版》系列中解释了传统规则:“虽然段落中的公式总是在二元操作和关系之后中断,但显示的公式总是在二元操作之前中断” [3]

遵循数学传统通常会产生更易读的代码:

# Yes:运算符和操作数很容易进行匹配
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

在Python代码中,只要约定在本地一致,就允许在二元运算符之前或之后中断。对于新代码,建议使用Knuth的样式。

空行

使用两个空行环绕顶级函数和类定义。

类中的方法定义由单个空行包围。

可以使用额外的空白行(谨慎地)来分离相关功能组。在一堆相关的单行(例如,一组虚拟实现)之间可以省略空行。

在函数中使用空行,谨慎地指示逻辑部分。

Python接受control-L(即^ L)换页符作为空格; 许多工具将这些字符视为页面分隔符,因此您可以使用它们来分隔文件相关部分的页面。请注意,某些编辑器和基于Web的代码查看器可能无法将control-L识别为换页符,并且会在其位置显示另一个字形。

源文件编码

核心Python发行版中的代码应始终使用UTF-8(或Python 2中的ASCII)。

使用ASCII(在Python 2中)或UTF-8(在Python 3中)的文件不应具有编码声明。

在标准库中,非默认编码应仅用于测试目的,或者当注释或文档字符串需要提及包含非ASCII字符的作者名称时; 否则,使用\x,\u,\U或\N转义是在字符串文字中包含非ASCII数据的首选方法。

对于Python 3.0及更高版本,标准库规定了以下策略(参见PEP 3131):Python标准库中的所有标识符必须使用仅ASCII标识符,并且应尽可能使用英语单词(在许多情况下,缩写和技术)使用的术语不是英语)。此外,字符串文字和注释也必须是ASCII格式。唯一的例外是

  1. 测试非ASCII功能的测试用例;
  2. 作者姓名。名字不是基于拉丁字母的作者必须提供他们名字的拉丁音译。

鼓励全球受众的开源项目采用类似的政策。

导入

# Yes: 分开的行
import os
import sys

# No: 在一行
import sys, os

但是可以这样:

from subprocess import Popen, PIPE
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example

然而,显示的指定相对导入路径是使用绝对路径的一个可接受的替代方案,特别是在处理使用绝对路径导入不必要冗长的复杂包布局时:

from . import sibling
from .sibling import example

标准库代码应避免复杂的包布局,并始终使用绝对导入。
永远不应该使用隐式相对导入,并且已经在Python 3中删除了。

from myclass import MyClass
from foo.bar.yourclass import YourClass

如果此拼写导致本地名称冲突,则拼写它们

import myclass
import foo.bar.yourclass

并使用“myclass.MyClass”和“foo.bar.yourclass.YourClass”。

以这种方式重新发布名称时,以下有关公共和内部接口的指南仍然适用。

模块级的双下划线(dunder)名称

模块级“dunder名“(以双下划线作为开头和结尾的名称),如allauthorversion等,除了future以为,应被放置在模块文档字符串之后,以及除from future 之外的import表达式之前。Python要求将来在模块中的导入,必须出现在除文档字符串之外的其他代码之前。
比如:

"""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
import sys

字符串引号

在Python中,单引号字符串和双引号字符串是相同的。该PEP不会对此提出建议。选择规则并坚持下去。但是,当字符串包含单引号或双引号字符时,请使用另一个字符串以避免字符串中出现反斜杠。它提高了可读性。

对于三引号字符串,始终使用双引号字符与PEP 257中的docstring约定一致。

表达式和语句中的空格

不可容忍

紧靠括号,括号或括号内。

Yes: spam(ham[1], {eggs: 2})
No:  spam( ham[ 1 ], { eggs: 2 } )
Yes: if x == 4: print x, y; x, y = y, x
No:  if x == 4 : print x , y ; x , y = y , x

Yes:

ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]

No:

ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]
Yes: spam(1)
No:  spam (1)
Yes: dct['key'] = lst[index]
No:  dct ['key'] = lst [index]

Yes:

x = 1
y = 2
long_variable = 3

No:

x             = 1
y             = 2
long_variable = 3

其他建议

Yes:

i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)

No:

i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)

Yes:

def complex(real, imag=0.0):
    return magic(r=real, i=imag)

No:

def complex(real, imag = 0.0):
    return magic(r = real, i = imag)

Yes:

def munge(input: AnyStr): ...
def munge() -> AnyStr: ...

No:

def munge(input:AnyStr): ...
def munge()->PosInt: ...

Yes:

def munge(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...

No:

def munge(input: AnyStr=None): ...
def munge(input: AnyStr, limit = 1000): ...

Yes:

if foo == 'blah':
    do_blah_thing()
do_one()
do_two()
do_three()

Rather not:

if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()

Rather not:

if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t < 10: t = delay()

Definitely not:

if foo == 'blah': do_blah_thing()
else: do_non_blah_thing()

try: something()
finally: cleanup()

do_one(); do_two(); do_three(long, argument,
                             list, like, this)

if foo == 'blah': one(); two(); three()

注释

与代码相矛盾的注释比没有注释更糟糕。始终优先考虑在代码更改时保持评论的最新状态!
注释应该是完整的句子。如果注释是短语或句子,则其第一个单词应该大写,除非它是以小写字母开头的标识符(永远不会改变标识符的情况!)。

如果注释很短,则可以省略最后的句点。块注释通常由完整句子构成的一个或多个段落组成,每个句子应以句点结束。

在句子结束期后你应该使用两个空格。

当用英文书写时,遵循Strunk and White 的书写风格。
来自非英语国家的Python程序员:请用英语撰写您的注释,除非您120%确信不会说不懂您语言的人不会阅读该代码。。

块注释

块注释通常适用于跟随它们的某些(或全部)代码,并缩进到与代码相同的级别。块注释的每一行开头使用一个#和一个空格(除非块注释内部缩进文本)。
块注释内部的段落通过只有一个#的空行分隔。

行内注释

有节制地使用行内注释。
行内注释是与代码语句同行的注释。行内注释和代码至少要有两个空格分隔。注释由#和一个空格开始。
事实上,如果状态明显的话,行内注释是不必要的,反而会分散注意力。比如说下面这样就不需要:

x = x + 1                 # Increment x

但有时,这样做很有用:

x = x + 1                 # Compensate for border

文档字符串

编写好的文档字符串(又名“docstrings”)的约定在PEP 257中是永恒的。

"""Return a foobang

Optional plotz says to frobnicate the bizbaz first.
"""

命名规范

Python库的命名规范很乱,从来没能做到完全一致。但是目前有一些推荐的命名标准。新的模块和包(包括第三方框架)应该用这套标准,但当一个已有库采用了不同的风格,推荐保持内部一致性。

至高原则

那些暴露给用户的API接口的命名,应该遵循反映使用场景而不是实现的原则。

描述:命名风格

有许多不同的命名风格。这里能够帮助大家识别正在使用什么样的命名风格,而不考虑他们为什么使用。
以下是常见的命名方式:

还有使用简短唯一前缀将相关名称组合在一起的风格。这在Python中并不常用,但为了完整性而提到它。例如,os.stat()函数返回一个元组,其元素传统上具有st_mode, st_size,st_mtime等名称。(这样做是为了强调与POSIX系统调用struct的字段的对应关系,这有助于程序员熟悉它。)
X11库的所有公共函数都加了前缀X。在Python里面没必要这么做,因为属性和方法在调用的时候都会用类名做前缀,函数名用模块名做前缀。
另外,下面这种用前缀或结尾下划线的特殊格式是被认可的(通常和一些约定相结合):

约定

应避免的名字

永远不要使用字母‘l’(小写的L),‘O’(大写的O),或者‘I’(大写的I)作为单字符变量名。
在有些字体里,这些字符无法和数字0和1区分,如果想用‘l’,用‘L’代替。

包名和模块名

模块应该有简短的全小写名称。如果提高可读性,可以在模块名称中使用下划线。Python包也应该有简短的全小写名称,但不鼓励使用下划线。

当用C或C ++编写的扩展模块具有提供更高级别(例如更多面向对象)的接口的Python模块时,C/C ++模块具有前导下划线(例如_socket)。

类名

类名通常应使用CapWords约定。

在接口被记录并主要用作可调用的情况下,可以使用函数的命名约定。

请注意,内置名称有一个单独的约定:大多数内置名称是单个单词(或两个单词一起运行),CapWords约定仅用于异常名称和内置常量。

异常名

因为异常应该是类,所以类命名约定适用于此处。但是,您应该在异常名称上使用后缀"Error"(如果异常实际上是错误)。

全局变量名

(我们希望这些变量仅用于一个模块内。)约定与函数的约定大致相同。

设计为通过M import *使用的模块应该使用__all__机制来防止输出全局变量,或者使用旧的约定为这些全局变量添加下划线(您可能希望这样做以表明这些全局变量是“模块非公开的” )。

函数名

函数名应该小写,如果想提高可读性可以用下划线分隔。
大小写混合仅在为了兼容原来主要以大小写混合风格的情况下使用(比如 threading.py),保持向后兼容性。

函数和方法参数

始终要将 self 作为实例方法的的第一个参数。
始终要将 cls 作为类静态方法的第一个参数。
如果函数的参数名和已有的关键词冲突,在最后加单一下划线比缩写或随意拼写更好。因此 class_ 比 clss 更好。(也许最好用同义词来避免这种冲突)

方法名和实例变量

使用函数命名规则:小写,必要时用下划线分隔,以提高可读性。

仅对非公共方法和实例变量使用一个前导下划线。

为避免与子类的名称冲突,请使用两个前导下划线来调用Python的名称修改规则。

Python使用类名来破坏这些名称:如果类Foo具有名为__a的属性,则Foo.__ a无法访问它。(坚持不懈的用户仍然可以通过调用Foo._Foo__a获得访问权限。)通常,双重前导下划线应该仅用于避免与设计为子类的类中的属性发生名称冲突。

注意:关于__names的使用存在一些争议(见下文)。

常量

常量通常在模块级别定义,并以全部大写字母书写,下划线分隔单词。示例包括 MAX_OVERFLOWTOTAL

继承的设计

始终决定一个类的方法和实例变量(统称为“属性”)是公共的还是非公共的。如有疑问,请选择非公开; 将公共属性设为非公开更容易公开。

公共属性是指您希​​望类的无关客户端使用的属性,您承诺避免向后不兼容的更改。非公开属性是指不打算由第三方使用的属性; 您不能保证非公共属性不会更改甚至不会被删除。

我们在这里不使用术语“私有”,因为在Python中没有属性是真正私有的(没有通常不必要的工作量)。

另一类属性是属于“子类API”的属性(通常在其他语言中称为“受保护”)。某些类旨在从中继承,以扩展或修改类的行为方面。在设计这样的类时,请注意明确决定哪些属性是公共的,哪些是子类API的一部分,哪些属性真正只能由基类使用。

考虑到这一点,这是Pythonic指南:

公共属性应该没有前导下划线。

如果公共属性名称与保留关键字冲突,请在属性名称后附加单个尾随下划线。这比缩写或损坏的拼写更可取。(但是,尽管有这个规则,'cls'是任何已知为类的变量或参数的首选拼写,尤其是类方法的第一个参数。)

注1:有关类方法,请参阅上面的参数名称建议。

对于简单的公共数据属性,最好只公开属性名称,而不使用复杂的访问器/ mutator方法。请记住,如果您发现简单的数据属性需要增加功能行为,Python提供了一条简单的未来增强路径。在这种情况下,使用属性隐藏简单数据属性访问语法背后的功能实现。

注1:属性仅适用于新式类。

注2:尝试保持功能行为副作用免费,尽管缓存等副作用通常很好。

注3:避免使用属性进行计算成本高昂的操作; 属性表示法使调用者相信访问(相对)便宜。

如果您的类要进行子类化,并且您具有不希望使用子类的属性,请考虑使用双前导下划线和没有尾随下划线来命名它们。这将调用Python的名称修改方法,其中类的名称被修改为属性名称。如果子类无意中包含具有相同名称的属性,这有助于避免属性名称冲突。

注1:请注意,在修改的名称中只使用简单的类名,因此如果子类选择相同的类名和属性名,则仍然可以获得名称冲突。

注2:名称修改可以使某些用途,例如调试和 __getattr__(),不太方便。但是,名称修改算法已有详细记录,并且易于手动执行。

注3:不是每个人都喜欢误拼。尽量在避免意外姓名冲突与潜在的高级调用间寻求平衡。

公共和内部的接口

任何向后兼容性保证仅适用于公共接口。因此,用户能够清楚地区分公共和内部接口是很重要的。

记录的接口被认为是公共的,除非文档明确声明它们是临时的或内部接口免于通常的向后兼容性保证。应假定所有未记录的接口都是内部接口。

为了更好地支持内省,模块应使用__all__属性在其公共API中显式声明名称。将__all__设置 为空列表表示该模块没有公共API。

即使适当地设置__all__,内部接口(包,模块,类,函数,属性或其他名称)仍应以单个前导下划线为前缀。

如果任何包含名称空间(包,模块或类)的内容被视为内部接口,则该接口也被视为内部接口。

应始终将导入的名称视为实现细节。其他模块不能依赖于对这些导入名称的间接访问,除非它们是包含模块的API的显式记录部分,例如os.path或从子模块公开功能的包的__init__模块。

编程建议

Yes:

if foo is not None:

No:

if not foo is None:

为了最大限度地减少所涉及的工作量,functools.total_ordering() 装饰器提供了一个生成缺失比较方法的工具。
PEP 207 指出Python实现了反射机制。因此,解析器会将 y > x 转变为 x < y,将 y >= x 转变为 x <= y,也会转换 x == yx != y 的参数。sort() 和 min()方法确保使用<操作符,max()使用>操作符。然而,最好还是实现全部六个操作符,以免在其他地方出现冲突。

Yes:

def f(x): return 2*x

No:

f = lambda x: 2*x

第一种形式意味着生成的函数对象的名称特别是'f'而不是泛型'<lambda>'。这对于一般的回溯和字符串表示更有用。使用赋值语句消除了lambda表达式可以在显式def语句上提供的唯一好处(即它可以嵌入到更大的表达式中)

基于可能需要捕获异常的代码的区别来设计异常层次结构 ,而不是引发异常的位置。旨在回答“出了什么问题?”的问题。以编程方式,而不是仅仅声明“发生了一个问题”(请参阅PEP 3151,了解本课程的示例是为内置异常层次结构学习的)

类命名约定适用于此处,但如果异常是错误,则应将后缀“Error”添加到异常类中。用于非本地流控制或其他形式的信令的非错误异常不需要特殊后缀。

类的命名规范适用于这里,但是你需要添加一个“Error”的后缀到你的异常类,如果异常是一个Error的话。非本地流控制或者其他形式的信号的非错误异常不需要特殊的后缀。
try:
    import platform_specific_module
except ImportError:
    platform_specific_module = None

如果只有一个except 块将会捕获到SystemExitKeyboardInterrupt异常,这样会很难通过Control-C中断程序,而且会掩盖掉其他问题。如果你想捕获所有指示程序出错的异常,使用 except Exception:(只有except等价于 except BaseException:)。
两种情况不应该只使用excpet块:

  1. 如果异常处理的代码会打印或者记录log;至少让用户知道发生了一个错误。

  2. 如果代码需要做清理工作,使用 raise..try…finally 能很好处理这种情况并且能让异常继续上浮。

    • 当给捕捉的异常绑定一个名字时,推荐使用在Python 2.6中加入的显式命名绑定语法:
try:
    process_data()
except Exception as exc:
    raise DataProcessingFailedError(str(exc))

为了避免和原来基于逗号分隔的语法出现歧义,Python3只支持这一种语法。

Yes:

try:
    value = collection[key]
except KeyError:
    return key_not_found(key)
else:
    return handle_value(value)

No:

try:
    # Too broad!
    return handle_value(collection[key])
except KeyError:
    # Will also catch KeyError raised by handle_value()
    return key_not_found(key)

Yes:

with conn.begin_transaction():
    do_stuff_in_transaction(conn)

No:

with conn:
    do_stuff_in_transaction(conn)

第二个例子没有提供任何信息去指明__enter____exit__方法在事务之后做出了关闭连接之外的其他事情。这种情况下,明确指明非常重要。

Yes:

def foo(x):
    if x >= 0:
        return math.sqrt(x)
    else:
        return None

def bar(x):
    if x < 0:
        return None
    return math.sqrt(x)

No:

def foo(x):
    if x >= 0:
        return math.sqrt(x)

def bar(x):
    if x < 0:
        return
    return math.sqrt(x)
Yes: if foo.startswith('bar'):
No: if foo[:3] == 'bar':
Yes: if isinstance(obj, int):

No: if type(obj) is type(1):

当检查一个对象是否为string类型时,记住,它也有可能是unicode string!在Python2中,strunicode都有相同的基类:basestring,所以你可以这样:

if isinstance(obj, basestring):

注意,在Python3中,unicodebasestring都不存在了(只有str)并且bytes类型的对象不再是string类型的一种(它是整数序列)

Yes: if not seq:
      if seq:

No: if len(seq):
      if not len(seq):
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:

功能注释

随着PEP 484的接受,功能注释的样式规则正在发生变化。

# type: ignore

如果这个靠近文件顶部; 这告诉类型检查器忽略所有注释。(在PEP 484中可以找到更细粒度的禁用类型检查器投诉的方法。)

参考

[1] PEP 7, Style Guide for C Code, van Rossum

[2] Barry's GNU Mailman style guide http://barry.warsaw.us/software/STYLEGUIDE.txt

[3] Donald Knuth's The TeXBook, pages 195 and 196.

[4] http://www.wikipedia.com/wiki/CamelCase

[5] Typeshed repo https://github.com/python/typeshed

[6] | Suggested syntax for Python 2.7 and straddling code https://www.python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code

上一篇下一篇

猜你喜欢

热点阅读