本文转载自:http://liyangliang.me/posts/2015/08/simple-python-style-guide/
仅仅作为学习使用
遵循良好的编码风格,可以有效的提高代码的可读性,降低出错几率和维护难度。在团队开发中,使用(尽量)统一的编码风格,还可以降低沟通成本。
网上有很多版本的编码规范,基本上都是遵循 PEP8 的规范:
除了在编码时主动遵循规范,还有很多有用的工具:
本文的内容主要摘自互联网上各种版本的规范,因为公司有些小伙伴代码风格不太好,所以整理了一份算是团队的编码规范。
IndentationError
,
后面加一个空格:
后面加一个空格#
后面加一个空格,但是 #!/usr/bin/python
的 #
后不能有空格+
, -
, *
, /
, |
, &
, =
=
两端不需要空格()
, {}
, []
)内的两端不需要空格;
隔开 使用 \
或 ()
控制换行,举例:
def foo(first, second, third, fourth, fifth,
sixth, and_some_other_very_long_param):
user = User.objects.filter_by(first=first, second=second, third=third) \
.skip(100).limit(100) \
.all()
text = ('Long strings can be made up '
'of several shorter strings.')
-
各种类型的命名规范:
Type | Public | Internal |
---|---|---|
Modules | lower_with_under |
_lower_with_under |
Packages | lower_with_under |
|
Classes | CapWords |
_CapWords |
Exceptions | CapWords |
|
Functions | lower_with_under() |
_lower_with_under() |
Global/Class Constants | CAPS_WITH_UNDER |
_CAPS_WITH_UNDER |
Global/Class Variables | lower_with_under |
_lower_with_under |
Instance Variables | lower_with_under |
_lower_with_under (protected) or __lower_with_under (private) |
Method Names | lower_with_under() |
_lower_with_under() (protected) or __lower_with_under() (private) |
Function/Method Parameters | lower_with_under |
|
Local Variables | lower_with_under |
from foo imort *
from ..utils import validator
,最好使用全路径导入(absolute imports)对于不同的 package,一个 import 单独一行,同一个 package/module 下的内容可以写一起:
# bad
import sys, os, time
# good
import os
import sys
import time
# ok
from flask import Flask, render_template, jsonify
为了避免可能出现的命名冲突,可以使用 as
或导入上一级命名空间
不要出现循环导入(cyclic import)
docstring
, 是 package, module, class, method, function 级别的注释,可以通过 __doc__
成员访问到,注释内容在一对 """
符号之间不要写错误的注释,不要无谓的注释
# bad 无谓的注释
x = x + 1 # increase x by 1
# bad 错误的注释
x = x - 1 # increase x by 1
优先使用英文写注释,英文不好全部写中文,否则更加看不懂
try/except
except
后面需要指定捕捉的异常,裸露的 except
会捕捉所有异常,意味着会隐藏潜在的问题except
语句,捕捉多种异常,分别做异常处理finally
子句来处理一些收尾操作 try/except
里的内容不要太多,只在可能抛出异常的地方使用,如:
# bad
try:
user = User()
user.name = "leon"
user.age = int(age) # 可能抛出异常
user.created_at = datetime.datetime.utcnow()
db.session.add(user)
db.session.commit() # 可能抛出异常
except:
db.session.rollback()
# better
try:
age = int(age)
except (TypeError, ValueError):
return # 或别的操作
user = User()
user.name = "leon"
user.age = age
user.created_at = datetime.datetime.utcnow()
db.session.add(user)
try:
db.session.commit()
except sqlalchemy.exc.SQLAlchemyError: # 或者更具体的异常
db.session.rollback()
finally:
db.session.close()
从 Exception
而不是 BaseException
继承自定义的异常类
object
类super
调用父类的方法join
方法拼接字符串string
模块的方法startswith
和 endswith
方法比较前缀和后缀format
方法格式化字符串list
, str
, tuple
, set
, dict
和 0
, 0.0
, None
都是 False
if some_list
而不是 if len(some_list)
判断某个 list
是否为空,其他类型同理is
和 is not
与单例(如 None
)进行比较,而不是用 ==
和 !=
if a is not None
而不是 if not a is None
isinstance
而不是 type
判断类型==
和 !=
与 True
和 False
比较(除非有特殊情况,如在 sqlalchemy 中可能用到) 使用 in
操作:
用 key in dict
而不是 dict.has_key()
# bad
if d.has_key(k):
do_something()
# good
if k in d:
do_something()
用 set
加速 “存在性” 检查,list
的查找是线性的,复杂度 O(n),set
底层是 hash table, 复杂度 O(1),但用 set
需要比 list
更多内存空间
dict
的 get
方法可以指定默认值,但有些时候应该用 []
操作,使得可以抛出 KeyError
for item in list
迭代 list
, for index, item in enumerate(list)
迭代 list
并获取下标sorted
和 list.sort
进行排序map
, reduce
, filter
和 lambda
,使用内建的 all
, any
处理多个条件的判断defaultdict
(Python 2.5+), Counter
(Python 2.7+) 等 “冷门” 但好用的标准库算法和数据结构with
语句处理上下文logging
记录日志,配置好格式和级别