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应该按照如下顺序成组安放:
- 标准库的导入
- 相关的第三方包的导入
- 本地应用/库的特定导入
-
对于内部包的导入是非常不推荐使用相对导入的。对所有导入总是使用包的绝对路径
-
从一个包含类的模块中导入类时,通常可以写成这样:
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
参考资料
如何使用Pylint来规范Python代码风格
PEP 8 - Style Guide for Python Code
转载请注明作者Jason Ding及其出处
Github博客主页(http://jasonding1354.github.io/)
CSDN博客(http://blog.csdn.net/jasonding1354)
简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)
网友评论
类方法才能那样用,使用@classmethod定义类方法,按约定,类方法的第一个参数为cls.