最近面试被问到没有看过原版的PEP8,因为简历里面有提及之前看过的《代码简洁之道》一书
关于代码规范这块,刚工作的时候看过不少,不过都是翻译版,后面公司也有定一套统一规范,基本就按着来了
趁这个机遇,自己把原版的PEP8翻译回顾一遍吧,带着审视自己的代码,应该会有新的收获
简介
本文档和PEP257文档改编于Guido的《python风格指南》,添加了Barry《代码风格建议》中的一些内容
并随着语言本身的变化而做出相应调整
如果项目本身有自己的代码规范,那么以项目本身规范为主,本文档为辅
不要盲目的追求一致性
Guido的一个重要见解是,代码总是读多于写。尽量提高代码的可读性,保持python的一致性。如PEP20所说,易读
风格指南是关于一致性的,这种一致性很重要,项目的一致性更重要,模块或方法的一致性是最重要的
然而,要知道什么时候需要一致,什么时候不需要。当发现或怀疑风格指南不适合时,需要看看别的例子,想想怎样才是适合的。
尤其是不要为了追求本文的一致性而破坏向后兼容。
一些不用遵守改规范的例子:
1.应用该规范会使阅读代码变得困难,即使是一直遵守该规范的人也难以理解。
2.需要和已存在的代码或周围的人的代码保持一致性——但反过来,或者可以重新制定规则
代码布局
缩进
使用四个空格
正确写法:
# 若第一行带有参数,则剩余行与参数位置对齐
# 第一行没有参数,且该语句后面会产生缩进,则剩余的行需要两级缩进,与后面语句区分开
# 若没有一行写完,剩余的行应该与它本身有一级缩进
错误:
# 有参数,但后面没有对齐参数
# 后面的语句有缩进,未能和该语句本身分开
tab还是空格
python3不支持空格和tab的混用,个人倾向于全空格
每行最大行数
多大79个字符
(实际运用中,我们是以公司显示屏能够一行显示完为标准)
在运算符之前还是之后分隔行
# No: 运算符隔得很远,一眼看过去,整个运算过程不清晰
# Yes: 可以清楚知道每个运算操作
其实运算符在哪里被分隔都可以,根据具体的情况,可读性高为准
空行
空两行:外部函数和类
空一行:类内部函数
多行:一系列相关函数
在函数中空一行表示逻辑的分离
源文件编码
python2中使用ASCII,python3用utf8,使用默认编码不要写编码说明
尽量用英文
(实际使用都是要声明用utf8)
import
模块的引用需要分开
No:
一个模块中同时引用两个方法是OK的
模块位于文件顶部,在模块声明描述之后,位于全局变量声明之前
不同模块引用的顺序:
1.标准库import
2.第三方库import
3.本地模块import
3个不同类型模块之间有一个空格
一般来说,比较推荐使用绝对路径引用模块
但绝对路径太长则没有必要这样写,会显得累赘,可以将上面的改成这样:
一般导入本地模块可以这么写:
如果MyClass和YourClass存在命名冲突,那么可以这样:
用 "myclass.MyClass" 和 "foo.bar.yourclass.YourClass"表示
from <module> import *
不提倡该写法,很容易造成命名冲突
表达式和语句中的空格
各种括号都不需要空格
Yes: spam(ham[1], {eggs: 2})
No: spam( ham[ 1 ], { eggs: 2 } )
在逗号、冒号、分隔符前面不需要空格
然而,在一个扩展空间,冒号左右空格需要一致,但是当一边没有值时,应该省略那边的空格
Yes:
No:
不需要多个空格来使得表达式的等号位置一致
Yes:
No:
其它建议
避免末尾带有空格
应该使得表达式的运算最后一步明显区别其它运算
Yes:
No:
不要在参数中的=两边加空格
Yes:
No:
显示的指定返回值
Yes:
No:
关于代码规范这块,刚工作的时候看过不少,不过都是翻译版,后面公司也有定一套统一规范,基本就按着来了
趁这个机遇,自己把原版的PEP8翻译回顾一遍吧,带着审视自己的代码,应该会有新的收获
简介
本文档和PEP257文档改编于Guido的《python风格指南》,添加了Barry《代码风格建议》中的一些内容
并随着语言本身的变化而做出相应调整
如果项目本身有自己的代码规范,那么以项目本身规范为主,本文档为辅
不要盲目的追求一致性
Guido的一个重要见解是,代码总是读多于写。尽量提高代码的可读性,保持python的一致性。如PEP20所说,易读
风格指南是关于一致性的,这种一致性很重要,项目的一致性更重要,模块或方法的一致性是最重要的
然而,要知道什么时候需要一致,什么时候不需要。当发现或怀疑风格指南不适合时,需要看看别的例子,想想怎样才是适合的。
尤其是不要为了追求本文的一致性而破坏向后兼容。
一些不用遵守改规范的例子:
1.应用该规范会使阅读代码变得困难,即使是一直遵守该规范的人也难以理解。
2.需要和已存在的代码或周围的人的代码保持一致性——但反过来,或者可以重新制定规则
代码布局
缩进
使用四个空格
正确写法:
# 若第一行带有参数,则剩余行与参数位置对齐
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)
错误:
# 有参数,但后面没有对齐参数
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)
tab还是空格
python3不支持空格和tab的混用,个人倾向于全空格
每行最大行数
多大79个字符
(实际运用中,我们是以公司显示屏能够一行显示完为标准)
在运算符之前还是之后分隔行
# No: 运算符隔得很远,一眼看过去,整个运算过程不清晰
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
# Yes: 可以清楚知道每个运算操作
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
其实运算符在哪里被分隔都可以,根据具体的情况,可读性高为准
空行
空两行:外部函数和类
空一行:类内部函数
多行:一系列相关函数
在函数中空一行表示逻辑的分离
源文件编码
python2中使用ASCII,python3用utf8,使用默认编码不要写编码说明
尽量用英文
(实际使用都是要声明用utf8)
import
模块的引用需要分开
Yes:
import os
import sys
No:
import sys, os
一个模块中同时引用两个方法是OK的
from subprocess import Popen, PIPE
模块位于文件顶部,在模块声明描述之后,位于全局变量声明之前
不同模块引用的顺序:
1.标准库import
2.第三方库import
3.本地模块import
3个不同类型模块之间有一个空格
一般来说,比较推荐使用绝对路径引用模块
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
但绝对路径太长则没有必要这样写,会显得累赘,可以将上面的改成这样:
from . import sibling
from .sibling import example
一般导入本地模块可以这么写:
from myclass import MyClass
from foo.bar.yourclass import YourClass
如果MyClass和YourClass存在命名冲突,那么可以这样:
import myclass
import foo.bar.yourclass
用 "myclass.MyClass" 和 "foo.bar.yourclass.YourClass"表示
from <module> import *
不提倡该写法,很容易造成命名冲突
表达式和语句中的空格
各种括号都不需要空格
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:
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 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)