PEP8是Python官网指导推荐的编程规范,OpenStack等项目都遵循它。上元也要求严格遵循该规范。本文中附着了PEP8原文,同时附带一篇中文翻译稿。推荐使用PyChram编辑python代码,它可自动提示那些不满足编程规范的代码, PyChram已经默认导入PEP8规范。如果已经习惯用Eclipse的PyDev,可以用文中附件--pep8检测工具检测自己的代码是否符合PEP8规范。
目录
2.6. 不要在一个关键字参数或者一个缺省参数值的 = 符号前后加一个空格 8
2.7. 通常不推荐使用复合语句(一行代码中有多条语句) 8
2.8. 通常情况下,一行代码包括一个小的if/for/while块,是可以的。但是多子句绝不可以。同样,需要避免折叠类似的长代码行! 8
4.8. 函数(Function)和方法(Method)参数 12
9.1. PyCharm中自带PEP8的检测,点击右边匡的黄色字体即可看到提示 20
4个空格的缩进(编辑器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格。
以下是带括号的一些缩进原则。
Yes:
#和括号开始的部分对齐
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)
No:
# 需要进一层的缩进,区分下一层的代码
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
如果if语句占用多行,推荐不需要特殊的缩进
#不需要特殊的缩进
if (this
and that):
do_something()
在闭合的括号中,后面的括号对齐变量名:
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
换行可以使用反斜杠,最好使用圆括号。换行点要在操作符的后边敲回车。
较长代码行折行的首选方法是在圆括号、方括号和花括号内使用Python的隐式续行方式。通过圆括号内的表达式的折行来把较长的代码行折成多行。同时确保适当的续行缩进。二元运算符的首选的折行处是在运算符之后,而不是之前。
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 -- values are %s, %s' %
(width, height))
Blob.__init__(self, width, height,
color, emphasis, highlight)
类和顶层函数定义之间空两行;
类中的方法定义之间空一行;
函数内逻辑无关段落之间空一行;
其他地方尽量不要再空行。
import xxx
class Rectangle(Blob):
def __init__(self, width, height,
color='black', emphasis=None, highlight=0):
... ...
def abc(self):
... ...
Python文件必须使用UTF-8格式。IDE文件编码方式设置成UTF-8。
python文件第一行写上,这样才能写中文注释
# -*- coding: utf-8 -*-
在代码中的字符串应该使用\x, \u, \U或者\N来包含非ASCII数据。
Yes:
import os
import sys
No:
import sys, os
按标准、第三方,上元外部模块,上元内部模块顺序依次排放,之间空一行。
import sys
Import os
from twisted.application import service
from ozcommon import configruration
Yes:
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
No:
from .import sibling
from .sibling import example
总体原则,避免不必要的空格。
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)
dict['key'] = list[index]
No
spam (1)
dict ['key'] = list [index]
Yes
x == 1
y = 1
No
x<>
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:
if foo == 'blah':
do_blah_thing()
do_one()
do_two()
do_three()
No:
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
No:
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()
不好理解的注释不如没有注释。注释要和代码保持与时俱进!注释应该是一条完整的句子。代码注释请用中文,除非语法特殊字符或者变量名等。
在一段代码前增加的注释。在‘#’后加一空格。段落之间以只有‘#’的行间隔。比如:
# 这是块注释段落1
#
# 这是块注释段落2
#
# 这是块注释段落3
在一句代码后加注释。
如果语句显而易见,那么内嵌注释是不必要的,比如:
x = x + 1 # x加1
而应该是有意义的注释。格式要求:语句后面要加2个空格,在加#号,之后再加一个空格,之后再写注释。
x = x + 1 # 边界弥补
避免无谓的注释
为所有的共有模块、函数、类、方法写文档描述;非共有的没有必要,但是可以写注释(在def的下一行)。
注意最重要的是,''' 作为多行的文档字符串的结束,应该单独一行,并且之前有一个空行
'''返回卷对象
该卷对象为你输入src_vol卷的克隆
'''
有如下命名规范:
lowercase 全小写字母
lower_case_with_underscores 使用下划线分隔的小写字母
UPPERCASE 大写字母
UPPER_CASE_WITH_UNDERSCORES 使用下划线分隔的大写字母
CapitalizedWords 多个单词无分隔符连接,每个单词首字母大写。大驼峰命名法。
名称前后下划线有特殊意义:
单下划线开始指弱'内部使用'。例如:from M import * 不会导入以下划线开始的对象。
_single_leading_underscore
单下划线结束用来避免与Python关键字冲突
Tkinter.Toplevel(master, class_='ClassName')
双下划线开始,该方法不会被子类继承。
class A(object):
def __init__(self):
self.__private()
self.public()
def __private(self):
print 'A.__private()'
def public(self):
print 'A.public()'
class B(A):
def __private(self):
print 'B.__private()'
def public(self):
print 'B.public()'
b = B()
上述代码正确的答案是:
A.__private()
B.public()
永远不要使用‘l’(小写的L),‘O’(大写的o)和I(大写的i)作为单字变量名。
在某些字体中,这些字很难和数字的0 和 1 区分。当打算用'l'的时候,用'L'来代替。
模块应该用简短的,全小写的名字。如果能增强可读性的话,可以使用下划线。 Python的包也要用全小写的,短名称,但是不建议用下划线。
因为模块名称和文件名关联,而且某些文件系统大小写不敏感,也会截断过长的名字。所以模块选用相当简短的名字是很重要的。 在Unix下不会有这样的问题,但是在早些的Mac、Windows 或者 DOS下会有这样的问题。
当用C或C++连编写一个含有Python模块提供更高层(比如,更加面向对象)接口的扩展模块时,这个C/C++模块要有一个前导下划线(例如 _socket)
类名要用首字母大写的规则。内部类,要加上前导下划线。
class SiteController(object):
Class __InnerInstance(object):
def __init__(self, a, b):
... ...
def __init__(self):
self.obj = __InnerInstance(1, 2)
Exception也是类,所以这里也用类名规则。一般产生了明显错误的异常定义后缀为Error的异常
class APIException(Exception):
def __init__(self):
... ...
class IOError(Exception):
... ...
这些规则和函数规则一样。
被设计为通过from M import *导入的模块。应该用__all__机制来防止导出全局。或者使用过去的全局变量前置下划线的规则(这是为了说明这些变量是'模块私有的')。
函数名应该用小写,为了增加可读性可以用下划线分隔
def add_instance(arg1, arg2):
... ...
def del_instance(arg1, arg2):
... ...
始终用self作为实例方法的第一个参数。
始终用cls作为类方法的第一个参数。
如果函数的参数名和保留字冲突。用结尾下划线比缩写或是滥用的组词更好。因此 class_ 比 clss好。(也许,更好的避免冲突的方式是用同义词。)
class A(object):
#类实例方法
def foo(self, x):
print 'executing foo(%s, %s)' % (self, x)
#类方法
@classmethod
def class_foo(cls, x):
print 'executing class_foo(%s, %s)' % (cls, x)
def fun1(self, class_=None):
... ...
使用函数命名规则:使用下划线分隔的小写字母会提高可读性。
只在私有方法和实例变量前使用单下划线。
class A(object):
# 共用方法
def fun_foo(self, x):
... ...
# 私有方法
def _fun2(self):
... ...
使用前导双下划线调用Python的名字变化规则来避免与子类中的名字冲突。
常量通常在模块级别中定义,用全大写和下划线分隔的字符来编写。例如
MAX_OVERFLOW
TOTAL
考虑一个类的方法或实例变量(总体而言:属性)应该是公用的或者非公用的。如果不能确定的话,设计为私有的。
公有属性,是你希望第三方使用的,并通过你的委托机制来避免由于属性变更导致的向后不兼容。 私有属性,是你不希望被第三方使用的。你不能保证私有属性不会改变甚至被删除。
贯穿着这样的思想,如下是Python的准则:
l 公有属性不应该用下划线开始
class A(object):
public_variable = 0
def public_fun(self):
print 'A.public()'
l 对于单一的公有数据属性,最好是直接用其属性名,而非复杂的存取器/突变期方法。
l 如果你的类打算用来继承的话,并且你的属性不希望子类继承,那么考虑用双下划线开头,不要有结尾下划线
class A(object):
def __init__(self):
self.__private()
self.public()
def __private(self):
print 'A.__private()'
def public(self):
print 'A.public()'
class B(A):
def __private(self):
print 'B.__private()'
def public(self):
print 'B.public()'
b = B()
上述代码正确的答案是:
A.__private()
B.B.public()
代码应该用不损害其他Python实现的方式去编写(PyPy, Jython, IronPython, Cython, Psyco 等) 例如,不要依赖于CPython的高效内置字符连接语句a += b or a = a + b.这些语句在Jython中运行较慢。在性能敏感的库中,应该用''.join() 来取代。这样可以保证在不同的实现中,字符链接花费的时间都呈线性。
l 与诸如None这样的字符比较时,要使用is or is not,永远不要用等于操作。同样地,在测试一个变量或参数默认值为None被设置为其他值时(比如if x表示if x is not None时),要注意。 这个值应该有一个能在布尔逻辑的上下文中为false的类型(比如容器)。
l 使用is not 操作符要比not ... Is好。虽然他们表达的意思相同,但是前一个更好理解:
Yes:
if foo is not None:
No:
if not foo is None:
l 当用复杂比较实现排序操作时,最好去实现全部六个操作(__eq__, __ne__, __lt__, __le__, __gt__, __ge__),而不是依靠其他的代码去实现一些怪异的比较。
l 使用基于对象的异常。模块或者包应该定义自己的异常基类,这个类应该继承自内置的Exception类。总要包含类文档语句,例如:
class MessageError(Exception):
'''Base class for errors in the email package.'''
在这里用到类命名规范。
l 当抛出一个异常的时候,使用raise ValueError('message')代替旧的raise ValueError, 'message'格式。推荐使用这种括弧的格式,当异常的参数很长或者是格式化字符串的时候,由于括号的关系,我们不需要使用连字符。旧的格式在Python 3 中被移除。
l 当捕获一个异常的时候,要用详细异常声明代替光秃秃的except: 语句.
例如:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
一个空的except:语句将会捕获 SystemExit 和 KeyboardInterrrupt 异常。这会使得很难用Control-C来中断一个程序,并且还会隐藏其他的问题。
如果你想捕获一个程序中的所有异常,使用except Exception。
l try里的东西要单纯,不要引入不可预见的其他异常被你的except捕获:
Yes:
try:
value = collection[key]
except KeyError:
return key_not_found(key)
else:
return handle_value(value)
No:
try:
return handle_value(collection[key])
except KeyError:
# handle_value函数内的KeyError 异常也会被捕获
return key_not_found(key)
l 使用String方法而非String模块。String方法更加快捷并且使用和unicode字符一样的API。如果需要向后兼容2.0之前的版本的话,可以不考虑这条规则。
Yes:
str = ‘abc’
str.upper()
No:
str = ‘abc’
import string
string.upper(s)
l 使用''.startswith() 和 ''.endswith()而非字符切片去检测前缀或后缀。
startswith() and endswith() 更加绿色,错误更少。例如:
Yes:
if foo.startswith('bar'):
No:
if foo[:3] == 'bar':
l 对象类型比较总要用 isinstance() 而非直接比较
Yes:
if isinstance(obj, int):
No:
if type(obj) is type(1):
当检测一个对象是否是字符串是,记住,它可能是unicode字符。在Python 2.3, str和unicode有同样的基类——basestring, 那么你可以这样做:
if isinstance(obj, basestring):
l 对于序列,(strings, lists, tuples),利用空序列为false这一点。
Yes:
if not seq:
if seq:
No:
if len(seq)
if not len(seq)
l 书写字面值时不要依靠后面的空格。这些后面的空格,视觉上难以区分,而且很多编辑器(或者,眼前的,reindent.py)会去掉他们。
l 别用‘==’进行布尔值和 True 或者 False 的比较
Yes:
if greeting:
No:
if greeting == True:
Worse:
if greeting is True:
l 总是使用def语句而不是一个lambda表达式赋值给一个变量
例如:
Yes:
def f(x): return 2*x
No:
f = lambda x: 2*x
1. IDE必须使用PyCharm
2. 一个函数长度不能超过100行,推荐在一个屏幕内
3. 不需要的代码一定删除,包括没有使用的import语句
4. 注释,log里不能出现名字等个人信息
5. 能找到公用代码的地方尽量用公用代代码,并主动把公用代码描述清楚
6. 关于配置文件
主要是/usr/share/sunyacloud/config-templates/xxx.ini.tmpl和每个服务下的config.spec
类型用[]标识,分级用[]的前套数表示,比如[[]]
等号前后有空格
[]前后,里面没有空格
[shapes]
[[__many__]]
ram = integer
cpus = float
7. 权限检查,log处理等通用函数建议用装饰器封装
8. 把注释中所有含有decompile文字都去掉。例如:# --== Decompile ==--
9. 把python代码中所有开始部分的#yes注释都去掉。
10. 建议在每个python文件的开头都使用我们公司代码的License和copyright说明文字。这样比较专业
# Copyright (c) 2011 sunya
# All Rights Reserved.
#
# Licensed under the sunya License, Version 1.0 (the 'License'); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.sunya.com/licenses/LICENSE-1.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
11. 禁止把一个非常复杂的字典变量,传递到很多方法中,让别人很难猜测字典中包含哪些内容;建议改成使用类对象传递
本文英文出处: http://www.python.org/dev/peps/pep-0008/
方法:1)解压附件
2)执行“python pep8.py --you want to check file--”。例如:
1) 执行pylint 2) 结果如下: 工具下载地址: http://pylint.org
联系客服