第5集 注释与代码规范

1. 注释的作用

注释是代码中不会被Python解释器执行的部分,用于:

  • 解释代码:说明代码的功能和意图
  • 提高可读性:让代码更容易理解
  • 便于维护:帮助他人(和未来的自己)理解代码
  • 临时禁用:临时禁用某些代码而不删除

2. 单行注释

使用#符号创建单行注释,#后面的内容都会被忽略。

2.1 基本用法

# 这是一个单行注释
print("Hello, World!")  # 这也是注释,在代码后面

# 计算两个数的和
a = 10
b = 20
result = a + b  # 结果是30
print(result)

2.2 注释位置

# 在代码行之前注释(推荐)
# 定义圆周率
pi = 3.14159

# 在代码行之后注释
radius = 5  # 圆的半径

# 独立的注释行
# 计算圆的面积
area = pi * radius ** 2

3. 多行注释

3.1 使用三引号

"""
这是一个多行注释
可以写很多行
用于解释复杂的函数或类
'''

'''
这也是多行注释
使用单引号的三引号也可以
'''

3.2 多行注释示例

"""
本函数用于计算圆的面积
参数:
    radius:圆的半径(浮点数)
返回:
    圆的面积(浮点数)
公式:
    面积 = π × r²
"""
def calculate_area(radius):
    pi = 3.14159
    return pi * radius ** 2

4. 注释的最佳实践

4.1 何时需要注释

# 1. 复杂的算法或逻辑需要注释
def fibonacci(n):
    """
    计算斐波那契数列的第n项
    使用动态规划方法,时间复杂度O(n)
    """
    if n <= 1:
        return n
    a, b = 0, 1
    for _ in range(2, n + 1):
        a, b = b, a + b
    return b

# 2. 不直观的代码需要注释
# 位运算:提取最低位的1
lowest_bit = x & -x

# 3. 重要的决策或TODO标记
# TODO: 优化这个算法的时间复杂度
# FIXME: 修复这里可能出现的边界情况

# 4. 简单的代码不需要注释
x = 5  # 定义x为5(不必要)
# 直接:x = 5

4.2 注释的风格

# 好的注释:解释为什么这样做,而不是做什么
# 使用缓存来避免重复计算(性能优化)
if key in cache:
    return cache[key]

# 坏的注释:重复代码内容
# 如果key在cache中,返回cache[key]
if key in cache:
    return cache[key]

5. 文档字符串(Docstring)

文档字符串是函数、类、模块的第一段三引号字符串,用于生成文档。

5.1 函数文档字符串

def add_numbers(a, b):
    """
    计算两个数的和

    参数:
        a (int/float):第一个数
        b (int/float):第二个数

    返回:
        int/float:两个数的和

    示例:
        >>> add_numbers(1, 2)
        3
        >>> add_numbers(1.5, 2.5)
        4.0
    """
    return a + b

5.2 类文档字符串

class Student:
    """
    学生类

    属性:
        name (str):学生姓名
        age (int):学生年龄
        scores (list):成绩列表

    方法:
        add_score(score):添加成绩
        get_average():计算平均成绩
    """

    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.scores = []

5.3 模块文档字符串

"""
学生信息管理系统模块

本模块提供了学生信息的增删改查功能
"""

# 模块代码...

6. 命名规范

6.1 变量命名规范

蛇形命名法(Snake Case):单词用下划线连接,全部小写

# 推荐:蛇形命名法
student_name = "张三"
user_age = 18
total_score = 100

# 不推荐:驼峰命名法(用于Java等语言)
studentName = "张三"
userAge = 18

# 不推荐:单个字母
n = "张三"
a = 18

# 布尔变量以is开头
is_valid = True
has_permission = False
is_empty = True

6.2 函数命名规范

# 推荐:动词或动词短语,蛇形命名法
def calculate_average(scores):
    """计算平均值"""
    return sum(scores) / len(scores)

def get_student_info(student_id):
    """获取学生信息"""
    pass

def is_valid_email(email):
    """验证邮箱格式"""
    pass

6.3 类命名规范

帕斯卡命名法(Pascal Case):每个单词首字母大写,无下划线

# 推荐:帕斯卡命名法
class Student:
    """学生类"""
    pass

class UserInfo:
    """用户信息类"""
    pass

class BankAccount:
    """银行账户类"""
    pass

6.4 常量命名规范

常量使用全大写,单词用下划线连接

# 推荐
PI = 3.14159
MAX_SIZE = 100
DEFAULT_TIMEOUT = 30

# 不推荐
pi = 3.14159
max_size = 100

7. 代码格式化

7.1 缩进

Python使用缩进来组织代码块,推荐使用4个空格。

# 推荐:4个空格缩进
if True:
    print("缩进正确")

# 不推荐:Tab缩进(混用Tab和空格会导致错误)
if True:
    print("混用Tab")

# 不推荐:不一致的缩进
if True:
  print("2个空格")
    print("4个空格")

7.2 行长度

建议每行不超过79个字符,超过则换行。

# 长行换行
result = (some_very_long_variable_name +
          another_long_variable_name +
          yet_another_long_variable_name)

# 或使用反斜杠
result = some_very_long_variable_name + \
         another_long_variable_name + \
         yet_another_long_variable_name

# 函数参数换行
def function_name(param1, param2, param3,
                   param4, param5):
    pass

7.3 空行

# 函数之间使用两个空行
def function1():
    pass


def function2():
    pass

# 类之间使用两个空行
class Class1:
    pass


class Class2:
    pass

# 函数内部逻辑块之间使用一个空行
def process_data(data):
    # 数据清洗
    cleaned_data = data.strip()

    # 数据转换
    result = cleaned_data.upper()

    return result

7.4 空格使用

# 运算符两侧加空格
x = 1 + 2
result = a * b + c / d

# 逗号后加空格
print(a, b, c)
def function(a, b, c):
    pass

# 函数调用的括号内不加空格
print("Hello")  # 正确
print( "Hello" )  # 不正确

# 列表、字典的括号内不加空格
numbers = [1, 2, 3]  # 正确
numbers = [ 1, 2, 3 ]  # 不正确

8. PEP 8规范

PEP 8是Python的官方代码风格指南,主要包括:

8.1 导入规范

# 导入应该放在文件开头
# 标准库导入
import os
import sys

# 第三方库导入
import numpy as np
import pandas as pd

# 本地应用/库导入
from my_module import my_function

# 每个导入占一行(推荐)
import os
import sys

# 不推荐
import os, sys

# 使用from...import时,明确列出导入的内容
from math import sqrt, pi

# 不推荐使用通配符导入
# from math import *  # 不推荐

8.2 类和方法顺序

class MyClass:
    """类文档字符串"""

    # 1. 类属性和类方法
    class_variable = 0

    # 2. 初始化方法
    def __init__(self, value):
        """初始化方法"""
        self.value = value

    # 3. 公共方法
    def public_method(self):
        """公共方法"""
        pass

    # 4. 保护方法(单下划线开头)
    def _protected_method(self):
        """保护方法"""
        pass

    # 5. 私有方法(双下划线开头)
    def __private_method(self):
        """私有方法"""
        pass

9. 代码检查工具

9.1 pylint

# 安装
pip install pylint

# 使用
pylint your_file.py

9.2 black(代码格式化工具)

# 安装
pip install black

# 使用
black your_file.py

9.3 flake8

# 安装
pip install flake8

# 使用
flake8 your_file.py

10. 综合示例

10.1 符合规范的代码示例

"""
学生成绩管理系统
实现学生成绩的录入、查询和统计功能
"""

import math
from typing import List, Dict


class Student:
    """
    学生类

    属性:
        name: 学生姓名
        age: 学生年龄
        scores: 成绩列表
    """

    def __init__(self, name: str, age: int):
        """
        初始化学生对象

        参数:
            name: 学生姓名
            age: 学生年龄
        """
        self.name = name
        self.age = age
        self.scores = []

    def add_score(self, score: float) -> None:
        """
        添加成绩

        参数:
            score: 成绩分数
        """
        if 0 <= score <= 100:
            self.scores.append(score)
        else:
            raise ValueError("成绩必须在0-100之间")

    def get_average(self) -> float:
        """
        计算平均成绩

        返回:
            平均成绩
        """
        if not self.scores:
            return 0.0
        return sum(self.scores) / len(self.scores)

    def __str__(self) -> str:
        """
        返回学生信息的字符串表示

        返回:
            学生信息字符串
        """
        avg = self.get_average()
        return f"姓名:{self.name},年龄:{self.age}岁,平均成绩:{avg:.1f}分"


def calculate_statistics(students: List[Student]) -> Dict[str, float]:
    """
    计算班级统计信息

    参数:
        students: 学生列表

    返回:
        包含统计信息的字典
    """
    total_students = len(students)
    if total_students == 0:
        return {"count": 0, "average": 0.0}

    averages = [s.get_average() for s in students]
    class_average = sum(averages) / len(averages)

    return {
        "count": total_students,
        "average": round(class_average, 2)
    }


def main():
    """主函数"""
    # 创建学生
    student1 = Student("张三", 18)
    student2 = Student("李四", 19)
    student3 = Student("王五", 18)

    # 添加成绩
    student1.add_score(90)
    student1.add_score(85)
    student1.add_score(95)

    student2.add_score(88)
    student2.add_score(92)
    student2.add_score(90)

    student3.add_score(75)
    student3.add_score(80)
    student3.add_score(85)

    # 输出学生信息
    students = [student1, student2, student3]
    for student in students:
        print(student)

    # 计算统计信息
    stats = calculate_statistics(students)
    print(f"\n班级统计:")
    print(f"  学生人数:{stats['count']}")
    print(f"  班级平均:{stats['average']}分")


if __name__ == "__main__":
    main()

11. 本集总结

本集我们学习了:

  • 单行注释和多行注释的写法
  • 文档字符串(Docstring)的使用
  • 变量、函数、类的命名规范
  • 代码格式化规范(缩进、空格、空行)
  • PEP 8代码风格指南
  • 代码检查工具的使用

核心要点

  1. 注释应该解释"为什么"而不是"做什么"
  2. 使用文档字符串为函数、类添加说明
  3. 遵循PEP 8规范,保持代码风格一致
  4. 变量名要有意义,遵循命名规范
  5. 使用代码检查工具保持代码质量

下一集预告:我们将学习算术运算符,掌握Python中的各种数学运算。

12. 课后练习

  1. 为之前编写的程序添加合适的注释
  2. 练习使用文档字符串为函数添加说明
  3. 检查你的代码是否符合PEP 8规范
  4. 重命名你的变量,使其更符合命名规范
  5. 尝试使用black或pylint检查代码

提示:良好的代码规范是成为优秀程序员的重要素养,从现在开始养成好习惯!

« 上一篇 基本输入输出操作 下一篇 » 算术运算符