Bootstrap

一文搞懂 PEP8 代码风格

0.为什么需要PEP8?

PEP8存在是为了提高代码的可读性。

1.命名约定

命名样式
类型命名约定例子
Class每个单词都大写字母开头;不要用下划线Model, MyClass
Constant使用大写字母;下划线分隔单词CONSTANT, MY_CONSTANT,MY_LONG_CONSTANT
Package使用小写单词;不用下划线分隔单词package, mypackage
Function使用小写字母;下划线分隔单词function, my_function
Variable使用小写字母;下划线分隔单词x, var,my_variable
Method使用小写字母;下划线分隔单词class_method, method
Module使用小写字母;下划线分隔单词module.py, my_module.py
Package使用小写单词;不用下划线分隔单词package, mypackage

举例:如何选择名称?

>>> # Not recommended(反例)
>>> x = 'John Smith'
>>> y, z = x.split()
>>> print(z, y, sep=', ')
'Smith, John'
>>> # Recommended(正例)
>>> name = 'John Smith'
>>> first_name, last_name = name.split()
>>> print(last_name, first_name, sep=', ')
'Smith, John'

解释:在反例中,我们需要追踪x,y,z的内容,显然不如正例明了。

2.代码布局

空行

用两个空行的情况:函数和函数,函数和类之间的分隔

class MyFirstClass:
    pass


class MySecondClass:
    pass


def top_level_function():
    return None

用一个空行的情况:类中的函数分隔

class MyClass:
    def first_method(self):
        return None

    def second_method(self):
        return None

在函数内部用少量的空格,显示清晰的步骤,如下举例:

def calculate_variance(number_list):
    sum_list = 0
    for number in number_list:
        sum_list = sum_list + number
    mean = sum_list / len(number_list)

    sum_squares = 0
    for number in number_list:
        sum_squares = sum_squares + number**2
    mean_squares = sum_squares / len(number_list)

    return mean_squares - mean**2
最大行长和换行

PEP 8 建议行数应限制为 79 个字符。
隐含延续:如果代码包含在圆括号、方括号或大括号中,Python 将假定行继续。举例:

#举例1:有圆括号
def function(arg_one, arg_two,
             arg_three, arg_four):
    return arg_one

# 举例2:在二元运算符之前中断
total = (first_variable
         + second_variable
         - third_variable)

如果不能用隐含延续,用反斜杠换行:

from mypkg import example1, \
    example2, example3

3.缩进

PEP8的缩进规则,如下:

  • 使用4个空格缩进
  • 更喜欢空格而不是制表符(Tabs)
  • 制表符和空格不能混用
x = 3
if x > 5:
    print('x is larger than 5')
换行后的缩进,有两种缩进样式:
  • 第一种:将缩进块与开始分隔符对齐
#举例1
def function(arg_one, arg_two,
             arg_three, arg_four):
    return arg_one

#举例2:只需要4个空格就可以与开始分隔符对齐
#这种情况多发生在if跨越多行的语句中,因为if、空格和左括号构成 4 个字符。
x = 5      
if (x > 3 and
    x < 10):
    # Both conditions satisfied
    print(x)

x = 5
if (x > 3 and
        x < 10):    # 也可以在续行上添加额外的缩进
    print(x)
  • 第二种:悬挂缩进
    意思是段落或语句中除了第一行之外的每一行都缩进。
#举例1:使用悬挂缩进时,第一行不能有参数
var = function(
    arg_one, arg_two,
    arg_three, arg_four)

#举例2:在续行上使用双缩进,提高可读性
def function(
        arg_one, arg_two,
        arg_three, arg_four):
    return arg_one
放置右括号的两种方法

关键要保持一致性,两种方法二选一即可。

#方法1:将右括号与上一行第一个非空白字符对齐
list_of_numbers = [
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
    ]

#方法2:将右括号与开始构造行的第一个字符对齐
list_of_numbers = [
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
]

4.注释

同行注释

用 >= 2个空格 分隔语句和注释
用 1和空格 分隔#和注释内容

x = 5  # This is an inline comment
换行注释

格式:用#开头,后跟一个空格;
缩进:注释块缩进到与被描述的代码相同的级别
长度:注释长度不得超过79个字符
其他:如果注释较多,也可以对注释分段。

def quadratic(a, b, c, x):
    # Calculate the solution to a quadratic equation using the quadratic
    # formula.
    #
    # There are always two solutions to a quadratic equation, x_1 and x_2.
    x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
    x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)
    return x_1, x_2
文档注释

用(""")或(’’’)

# 举例1:将结束多行注释的”“”单独放一行
def quadratic(a, b, c, x):
    """Solve quadratic equation via the quadratic formula.

    A quadratic equation has the following form:
    ax**2 + bx + c = 0

    There always two solutions to a quadratic equation: x_1 & x_2.
    """
    x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
    x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)

    return x_1, x_2

# 举例2:对于单行文档注释,保持“”“在同一行
def quadratic(a, b, c, x):
    """Use the quadratic formula"""
    x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
    x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)

    return x_1, x_2

5.表达式和语句中的空格

当=用于为参数分配默认值时,不要用空格。
# Recommended
def function(default_parameter=5):
    # ...

# Not recommended
def function(default_parameter = 5):
    # ...
当有多个运算符,在优先级最低的运算符附近加空格
# Recommended:and优先级低
if x>5 and x%2==0:
    print('x is larger than 5 and divisible by 2!')
    
# Recommended:+优先级低
y = x**2 + 5
z = (x+y) * (x-y)

# Not Recommended
y = x ** 2 + 5
z = (x + y) * (x - y)
一般在,后加空格
# 举例1
# Recommended
my_list = [1, 2, 3]

# Not recommended
my_list = [ 1, 2, 3, ]

# 举例2
# Recommended
print(x, y)

# Not recommended
print(x , y)

6.编程建议

不要将bool值与等价运算符混用

# Recommended
if my_bool:
    return '6 is bigger than 5'

# Not recommended
my_bool = 6 > 5
if my_bool == True:
    return '6 is bigger than 5'

任何空list,空string,空tuple都是False

# Recommended
my_list = []
if not my_list:
    print('List is empty!')

# Not recommended
my_list = []
if not len(my_list):    # 不用判断长度
    print('List is empty!')

7.工具和技巧

Linters

Linter 是检查代码风格和错误的小工具。类似于word中的拼音检查,只是word检查的是自然语言,Linter检查的是机器语言。
对于Python代码的Linter第三方库:pycodestyle,flake8

自动修正

自动修正的第三方库:black

- 写在最后

边记录边学习,慢慢积累,日日提高。