原始笔记

Coding Conventions

Coding Conventions

正文

PEP 8

Indentation

use 4 spaces per indentation level - so 4 spaces on level one, 8 spaces on level two and so on. 推荐使用:

悬挂缩进

第一行只写到左括号,后续内容统一多缩进一级:

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)

右括号与语句起始位置对齐。

Maximum Line Length

All lines should be up to 80 characters long; for lines containing comments or docstrings (to be covered later) the line length limit should be 73 表达式过长时推荐用()包裹, 不推荐用\ 把下面这种格式作为默认规范:

if (
    first_condition
    and second_condition
):
    do_something()

列表、函数调用、复杂表达式也采用同样原则:左括号后换行,内容缩进一级,右括号与语句起始位置对齐。

长表达式拆成多行时,把二元运算符放在下一行开头,而不是上一行末尾。

推荐写法:

income = (
    gross_wages
    + taxable_interest
    + (dividends - qualified_dividends)
    - ira_deduction
    - student_loan_interest
)

不推荐:

income = (
    gross_wages +
    taxable_interest +
    (dividends - qualified_dividends) -
    ira_deduction -
    student_loan_interest
)

Blank lines

1. 顶层函数和类之间空两行

“顶层”指直接定义在 Python 模块中,不属于其他类或函数。

import math

def calculate_area(radius):
    return math.pi * radius**2

class Circle:
    pass

def calculate_diameter(radius):
    return radius * 2

这里:

  • import 与第一个顶层定义之间有两行空行;

  • 顶层函数与类之间有两行空行;

  • 两个顶层函数之间也应空两行。 标准库导入与项目内部导入之间保留一行空行即可:

import argparse

from inflammation import models, views

2. 类中的方法之间空一行

class Circle:
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return math.pi * self.radius**2

    def diameter(self):
        return self.radius * 2

类中的方法属于同一个类,关系更紧密,因此只空一行。

3. 函数内部可以少量使用空行

函数内部的空行用于划分逻辑阶段:

def process_records(records):
    valid_records = [
        record for record in records
        if record.is_valid()
    ]

    sorted_records = sorted(
        valid_records,
        key=lambda record: record.timestamp,
    )

    return generate_report(sorted_records)

推荐

def add_numbers(a, b):
    result = a + b
    return result

4. 装饰器与定义之间不要空行

@app.route("/users")
def get_users():
    return users

White spaces

1. 括号内部不要加无意义空格

推荐:

my_function(colour[1], {id: 2})

不推荐:

my_function( colour[ 1 ], { id: 2 } )

2. 逗号、分号、冒号前不留空格

推荐:

print(x, y)
mapping = {"name": "Alice"}

不推荐:

print(x , y)
mapping = {"name" : "Alice"}

一般规律:

标点前无空格,标点后通常一个空格

3. 切片中的冒号是特殊情况

简单切片不加空格:

values[1:5]
values[:5]
values[1:]
matrix[:, 1]

复杂切片中,冒号可以近似看作低优先级二元运算符,两侧保持相同数量的空格:

values[start + offset : stop + offset]

而不要一边有、一边没有:

values[start + offset: stop + offset]  # 不对称

8. 二元运算符两侧通常各一个空格

赋值运算符

x = 1

增强赋值

x += 1
total -= discount

比较运算符

x == 1
x != 1
x <= 10

成员运算符

item in collection
item not in collection

身份运算符

value is None
value is not None

布尔运算符

condition_a and condition_b
condition_a or condition_b
not condition_a

9. 普通赋值中的 = 两侧有空格

axis = "x"
angle = 90
size = 450

这里 = 表示执行赋值,因此两侧各一个空格。

10. 关键字参数中的 = 两侧不加空格

函数调用:

my_function(
    1,
    2,
    axis=axis,
    angle=angle,
    size=size,
    name=name,
)

这里的 axis=axis 不是普通赋值语句,而是在指定:

参数 axis 接收右侧 axis 变量的值

因此不加空格。

推荐:

draw(size=450, angle=90)

不推荐:

draw(size = 450, angle = 90)

11. 无类型注解的默认参数也不加空格

def draw(size=450, angle=90):
    pass

但当参数包含类型注解时,PEP 8 推荐在默认值的 = 两侧加空格:

def draw(size: int = 450, angle: int = 90):
    pass

对比:

def draw(size=450):          # 无类型注解
    pass

def draw(size: int = 450):   # 有类型注解
    pass

Naming Conventions

不同对象的推荐命名

变量:snake_case

变量名应说明它存储的具体内容。

推荐:

patient_name = "Alice"
temperature_readings = [36.5, 37.1]
number_of_records = 20

函数:snake_case,并使用动词

函数名应说明它执行什么操作:

calculate_average()
load_patient_records()
validate_user_input()
send_email()

类:PascalCase,并使用名词

类通常表示一种对象或概念,因此一般使用名词:

class PatientRecord:
    pass

class TemperatureAnalyzer:
    pass

class HTTPServerError(Exception):
    pass

模块:简短、全小写

Python 文件名就是模块名:

models.py
analysis.py
data_loader.py
temperature_utils.py

可以使用下划线提高可读性:

data_processing.py

不推荐:

DataProcessing.py
patient-records.py
VeryLongModuleForProcessingPatientData.py

模块名不能使用连字符 -,因为它会被解释为减号,无法正常导入:

import data-processing  # 错误

包:简短、全小写,尽量不用下划线

包是包含多个模块的目录:

inflammation/
datatools/
analytics/

PEP 8 对包名比模块名更倾向于简短连续的小写形式:

datatools

而不是:

data_tools

不过实际项目中带下划线的包名也很常见,仍应优先遵循项目规范。

实践中的推荐规则

对象 推荐风格 示例
变量 snake_case patient_name
函数、方法 snake_case calculate_mean()
常量 UPPER_CASE MAX_RETRIES
PascalCase PatientRecord
异常类 PascalCase InvalidDataError
模块 全小写,可加下划线 data_loader.py
简短全小写 datatools

Comments

Block comment:块注释

块注释用于解释它后面的一段代码,并与这段代码保持相同缩进。

格式要求:

  • 每行以 # 开头;
  • # 后有一个空格;
  • 写成完整句子;
  • 与所描述的代码处于相同缩进层级。
def calculate_discount(user):
    # Premium users receive the historical discount rate to
    # preserve compatibility with existing subscriptions.
    discount_rate = 0.2 if user.is_premium else 0.1
    return discount_rate

Inline comment:行内注释

行内注释放在语句末尾。

PEP 8 的格式是:

  • 代码和注释之间至少两个空格;
  • # 开头;
  • 谨慎使用。
retry_count += 1  # The first attempt is numbered zero.

行内注释适合解释非常局部、非常简短的特殊情况。

DocString

Google 风格

def fibonacci(n):
    """Calculate the nth Fibonacci number.

    Args:
        n: Index of the Fibonacci number.

    Returns:
        The nth Fibonacci number.

    Raises:
        ValueError: If n is negative.
    """

Switch to English