Python官方编码规范

PEP介绍

PEP是 Python Enhancement Proposal 的缩写,是Python增强建议书的意思。
Python的代码风格由PEP 8描述。这个文档描述了Python编程风格的方方面面。在遵守这个文档的条件下,不同程序员编写的Python代码可以保持最大程度的相似风格。这样就易于阅读,易于在程序员之间交流。

命名规则

不同的命名风格

有许多不同的命名风格。以下的有助于辨认正在使用的命名风格,这独立于它们的作用。

  • 小写串 (lowercase)
  • 带下划线的小写串 (lower_case_with_underscores)
  • 大写串 (UPPERCASE)
  • 带下划线的大写串 (UPPER_CASE_WITH_UNDERSCORES)
  • 首字母大写单词串 (CapitalizedWords) (或 CapWords、CamelCase,因其字母看起来错落有致,故得此名)
    注意: 在CapWords中使用缩写,需要把缩写的所有字母大写。故HTTPServerError比HttpServerError更好。
  • 混合大小写串 (mixedCase) (与首字母大写串不同之处在于第一个字符是小写的!)
  • 带下划线的首字母大写串 (Capitalized_Words_With_Underscores) (丑陋!)

避免采用的名字

决不能使用字母'l'(L的小写字母)、'O'(o的大写字母)、'I'(i的大写字母)) 作为单个字符的变量名。
在一些字体中,这些字符不能与数字1和0区别开。当想要使用'l'时,用'L'代替它。

包和模块名(Package and Module Names)

模块名应该是简短的、全部小写的名字。可以在模块名中使用下划线以提高可读性。Python包名也应该是简短的、全部小写的名字,尽管不推荐使用下划线。
因为模块名被映射到文件名,有些文件系统大小写不敏感并且截短长名字,所以把 模块名选择为相当短就很重要了——这在Unix上不是问题,但当把代码迁移到Mac、Windows或DOS上时,就可能是个问题了。
当一个用C或C++写的扩展模块,有一个伴随的Python模块来提供一个更高层(例如,更面向对象)的接口时,C/C++ 模块名有一个前导下划线 (如:_socket)。

类名(Class Names)

几乎没有例外,类名使用首字母大写单词串(CapWords)的约定。内部使用的类使用一个额外的前导下划线。

异常名 (Exception Names)

因为异常应该是类,故类命名约定也适用于异常。然而,你应该对异常名添加后缀"Error"(如果该异常的确是一个错误)。

全局变量名(Global Variable Names)

(我们希望这些变量只打算用于一个模块内部)。
对设计为通过"from M import "来使用的模块,应采用all机制来防止导出全局变量;或者使用旧的约定,为该类全局变量加一个前导下划线(可能你想表明这些全局变量是只限制在该模块内部使用,"module non-public")。

补充:
在python的module中,可以使用 all 函数来定义这个module像其他引用自己的module导入的变量:

__all__ = ['bar', 'baz']
waz = 5
bar = 10

当另一个模块中使用import *声明,waz和bar变量不会被导入,all可以隐藏不想被import的默认值。

函数名(Function Names)

函数名应该为小写,必要时可用下划线分隔单词以增加可读性。
混合大小写 (mixedCase) 仅被允许用于这种风格已经占优势的上下文 (如: threading.py),以便保持向后兼容。

函数和方法的参数(Function and method arguments)

对实例的方法,总是用'self'做第一个参数。
对类的方法,总是用'cls'做第一个参数。
(如果函数的参数名与保留关键字冲突,在参数名后加一个下划线,比用缩写、错误的拼写要好。因此"print_"比 "prnt"好。也许使用同义词来避免冲突更好)

补充:
python的类中,普通方法的第一个参数需要是self,它表示一个具体的实例本身;如果用了staticmethod,那么就可以无视这个self,而将这个方法当成一个普通的函数使用;而对于classmethod,它的第一个参数不是self,是cls,它表示这个类本身。

>>> class A(object):
        def foo1(self):
            print "Hello",self
        @staticmethod
        def foo2():
            print "hello"
        @classmethod
        def foo3(cls):
            print "hello",cls

>>> a = A()
>>> a.foo1()          #最常见的调用方式,但与下面的方式相同
Hello <__main__.A object at 0x9f6abec>
>>> A.foo1(a)         #这里传入实例a,相当于普通方法的self
Hello <__main__.A object at 0x9f6abec>
>>> A.foo2()          #这里,由于静态方法没有参数,故可以不传东西
hello
>>> A.foo3()          #这里,由于是类方法,因此,它的第一个参数为类本身。
hello <class '__main__.A'>
>>> A                 #可以看到,直接输入A,与上面那种调用返回同样的信息。
<class '__main__.A'>

方法名和实例变量(Method Names and Instance Variables)

采用函数命名规则:小写单词,必要时可用下划线分隔单词以增加可读性。
仅对 non-public 方法和实例变量采用一个前导下划线。

为避免与子类命名冲突,采用两个前导下划线来触发 Python 的命名重整规则。
Python用类名重整这些名字:如果类Foo有一个属性名为__a,它不能以Foo.__a访问(执著的用户还是可以通过Foo._Foo__a得到访问权)。通常,双 前导下划线仅被用来避免与基类的属性发生名字冲突。

谨记python特色的命名惯例

  • 公开属性应该没有前导下划线
  • 如果公开属性名和保留关键字冲突,在你的属性名后添加一个后置下划线
  • 对简单的公开数据属性 (data attribute),最好只暴露属性名,没有复杂的访问/修改方法
    谨记Python为将来增强提供了一条容易的途径,你应该发现简单数据属性需要增加功能行为。在那种情况,用特性(properties)把功能实现隐藏在简单数据属性访问语法后面。
  • 以单一下划线的变量名(_X)不会被from module import *语句导入。一个前导下划线的函数是私有函数。
    Python 中不存在私有变量一说,若是遇到需要保护的变量,使用小写和一个前导下划线。但这只是程序员之间的一个约定,用于警告说明这是一个私有变量,外部类不要去访问它。但实际上,外部类还是可以访问到这个变量。
  • 前后有两个下划线的变量名(X)是系统定义的变量名,对解释器有特殊意义。包括两个前导下划线,两个后置下划线的函数名,这种风格只应用于特殊函数,比如操作符重载等。
  • 以两个下划线开头,但结尾没有两个下划线的变量名(__X)是类的本地变量

代码布局

缩进(Indentation)

每级缩进用 4 个空格。
绝不要混合使用 tab 和空格。
最流行的 Python 缩进方式是仅使用空格,其次是仅使用制表符。混合着制表符和空 格缩进的代码将被转换成仅使用空格。调用 Python 命令行解释器时使用 -t 选项, 可对代码中不合法的混用制表符和空格发出警告 (warnings)。使用 -tt 时警告将变 成错误。这些选项是被高度推荐的。
对新项目,强烈推荐只用空格,而不是用tabs。大多数编辑器拥有使之易于实现的功能。

最大行宽(Maximum Line Length)

限制所有行的最大行宽为79字符。
折叠长行的首选方法是使用Python支持的圆括号、方括号(brackets)和花括号(braces)内的行延续。如果需要,你可以在表达式周围增加一对额外的圆括号,但是有时使用反斜杠看起来更好。确认恰当地缩进了延续的行。

class Rectangle(Blob): 
    def __init__(self, width, height,  
        color='black', emphasis=None, highlight=0): 
        if width == 0 and height == 0 and \  
            color == 'red' and emphasis == 'strong' or \ highlight > 100:  
            raise ValueError("sorry, you lose")  
        if width == 0 and height == 0 and (color == 'red' or  
                emphasis is None): 
            raise ValueError("I don't think so")  
        Blob.__init__(self, width, height,  
                    color, emphasis, highlight) 

空行(Blank Lines)

用两行空行分割顶层函数和类的定义。
类内方法的定义用单个空行分割。
在函数中使用空行时,请谨慎的用于表示一个逻辑段落。


导入 (Imports)

  • 通常应该在单独的行中导入:
    Yes: import os
    import sys

No: import sys, os
但是这样也是可以的:
from subprocess import Popen, PIPE

  • Imports通常被放置在文件的顶部,仅在模块注释和文档字符串之后,在模块的全局变量和常量之前。

  • Imports应该按照如下顺序成组安放:

  1. 标准库的导入
  2. 相关的第三方包的导入
  3. 本地应用/库的特定导入
  • 对于内部包的导入是非常不推荐使用相对导入的。对所有导入总是使用包的绝对路径

  • 从一个包含类的模块中导入类时,通常可以写成这样:
    from myclass import MyClass
    from foo.bar.yourclass import YourClass
    如果这样写导致了本地名字冲突,那么就这样写:
    import myclass
    import foo.bar.yourclass
    并使用"myclass.MyClass" and "foo.bar.yourclass.YourClass"


在表达式和语句中的空格(Whitespace in Expressions and Statements)

  • 紧挨着圆括号、方括号和花括号:
    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: spam(1)
    No: spam (1)
  • 紧贴在索引或切片 (indexing or slicing) 开始的开式括号前:
    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

注释(Comments)

同代码不一致的注释比没注释更差。当代码修改时,始终优先更新注释!
注释应该是完整的句子。如果注释是一个短语或句子,首字母应该大写,除非它是一个以小写字母开头的标识符(永远不要修改标识符的大小写)。
如果注释很短,可以省略末尾的句号。注释块通常由一个或多个段落组成,段落是由完整的句子构成的,每个句子应该以句号结尾。
你应该在结束语句的句点(a sentence-ending period)后使用两个空格。
非英语国家的Python程序员:请用英语书写你的注释,除非你120%的确信代码永远不会被不懂你的语言的人阅读。

注释块(Block Comments)

注释块通常应用于跟随其后的一些 (或者全部) 代码,并和这些代码有着相同的缩进 层次。注释块中每行以 '#' 和一个空格开始 (除非它是注释内的缩进文本)。
注释块内的段落以仅含单个 '#' 的行分割。

行内注释(Inline Comments)

节俭使用行内注释。
一个行内注释是和语句在同一行的注释。行内注释应该至少用两个空格和语句分开。 它们应该以一个 '#' 和单个空格开始。
行内注释不是必需的,事实上,如果说的是显而易见事,还会使人分心。不要这样做 :
x = x + 1 # Increment x
但是有时,这样是有益的:
x = x + 1 # Compensate for border