玛卡巴卡的blog 玛卡巴卡的blog
首页
提问箱
自传
植物分类
关于

玛卡巴卡

短暂的休息,是为了更好的再出发 有我爱和爱我的人,便什么都不会怕——
首页
提问箱
自传
植物分类
关于
  • 技术分享
玛卡巴卡
2026-01-22
目录

python coding 代码规范

#

# Python coding时该注意的代码规范

作为一名程序员,我们不可避免的要大量coding,虽然有了AI的帮助,但是并不是所有环境下AI都适用(某大厂甚至还限制使用外部ai哼),所以难免需要自己来coding,当代码的行数一多,阅读+理解代码便成为一个NP难的问题(因为debug是NP难的问题),所以为了让别人(和我们自己)更容易看懂我们的代码,也让代码看上去更整洁好看,我们需要一个代码规范,于是让我们掌声有请——

PEP 8 – Style Guide for Python Code

PEP 是 Python Enhancement Proposal(Python 增强提案)的缩写,而第 8 号提案专门讨论的是 Style Guide for Python Code。它由 Python 的创始人 Guido van Rossum 等人在 2001 年编写,核心哲学只有一句话:“代码被阅读的次数远多于被编写的次数”(Readability counts)。

首先要提一嘴,我们其实有现成的代码格式化工具:Black (opens new window),这里仅仅提供教程,大家感兴趣的可以自行配置(玛卡巴卡已经配置了嘻嘻)

下面分几个板块来讲讲 PEP 8 主要的规范包含哪些

# 1. 代码布局(缩进、行宽、换行、空行)

这一块决定了代码“第一眼是否顺”,也是团队协作里最能减少争论的一部分。

# 1.1 缩进:4 个空格,别用 Tab

  • 每层缩进 4 个空格。
  • 不要混用 Tab 与空格(IDE 里把 Tab 自动转换为空格最省事)。这是因为Tab只是一个逻辑字符在不同IDE(代码编辑器)中表示的宽度可能不一样,这样在不同的编辑器中打开时代码可能就格式不一样,解码的时候可能就会出问题

推荐

def foo(x):
    if x > 0:
        return x
    return 0
1
2
3
4

不推荐(Tab/缩进不一致)

def foo(x):
\tif x > 0:
\t    return x
1
2
3

# 1.2 行宽:尽量不超过 79(注释/文档 72)

  • 代码行建议 <= 79 字符。
  • docstring 和长注释建议 <= 72 字符(更适合阅读器/终端)。

# 1.3 长表达式换行:用括号,避免反斜杠

  • 换行优先用 () [] {} 的隐式换行:Python 解释器有一个特性,当它检测到括号(小括号 ()、中括号 []、花括号 {})未闭合时,会自动将后续行视为当前行的延续。这种方式被称为“隐式续行”。。
  • 反斜杠 \ 容易出坑(尾随空格、合并冲突等),尽量避免
    • 不可见的语法错误(尾随空格): 反斜杠必须是该行的最后一个字符。如果在反斜杠后面不小心输入了一个空格或制表符,Python 解释器会抛出 SyntaxError: unexpected character after line continuation character。由于空格是不可见的,这类错误往往极难排查。
    • 维护困难: 在后续的代码重构或合并冲突(Merge Conflict)中,反斜杠极易被误删或遗漏,导致逻辑中断。

推荐(括号隐式换行)

total = (
    base_price
    + shipping_fee
    - discount
    + tax
)
1
2
3
4
5
6

不推荐(反斜杠换行)

total = base_price + shipping_fee \
        - discount + tax
1
2

# 1.4 空行:用来“分组”,让结构一眼清楚

高频规则:

  • 顶层 def / class 之间:空 2 行
    • 两个顶级类之间
    • 两个顶级函数之间
    • 顶级类与顶级函数之间
  • 类内部方法之间:空 1 行
  • 逻辑段落之间:适当空 1 行,这类似于文章中的分段。如果一个函数较长,将其拆分为“数据准备”、“核心计算”、“结果返回”等逻辑段落,并用空行分隔,可以显著提升可读性。

推荐

import os
import sys


class UserService:
    def create_user(self, name):
        return {"name": name}

    def delete_user(self, user_id):
        ...
1
2
3
4
5
6
7
8
9
10

# 2. 导入(imports)顺序与写法

导入写得好,文件“可读性”和“可维护性”都会明显提升。

# 2.1 导入分组顺序:标准库 → 第三方 → 本地

并且每组之间空一行。

推荐

import json
from pathlib import Path

import requests

from myapp.config import settings
from myapp.utils import slugify
1
2
3
4
5
6
7

小tips: 可以通过运行

pip show [package_name]来快速检验
1

如果是第三方库,会显示该库的版本、摘要、作者及安装位置(通常在 site-packages 目录下) 如果是标准库,会提示 Package(s) not found,因为标准库不是通过 pip 安装的

# 2.2 避免通配符导入:from x import *

通配符会污染命名空间,读代码时很难知道一个名字来自哪里。

推荐

from math import sqrt
1

不推荐

from math import *
1

# 2.3 导入要放在文件顶部

除了少数情况(比如为了避免循环依赖、或性能原因的延迟导入)之外,都放顶部。


# 3. 空格使用(最常见的“格式化争议”)

这一块非常高频,且最容易被自动格式化工具统一

# 3.1 运算符两边加空格(赋值、比较、算术等)

推荐

x = 1
y = x + 2
ok = (a == b)
1
2
3

不推荐

x=1
y=x+2
ok=(a==b)
1
2
3

# 3.2 函数调用/索引的括号内一般不加空格

在处理括号时,应遵循“边缘紧凑、元素分隔”的原则。这意味着括号与其包含的第一个/最后一个字符之间不留空格,但多个参数/元素之间必须通过空格保持清晰。

  • 括号边缘:紧贴起始括号之后和结束括号之前不加空格。
  • 参数分隔:在函数调用、定义或列表/元组中,逗号后面必须跟一个空格,但逗号前面严禁有空格。
  • 参数赋值:在函数定义(默认参数)或函数调用(关键字参数)中,= 两侧不加空格。
  • 调用关联:函数名与左括号之间、索引变量名与左中括号之间不加空格。

推荐

# 括号边缘紧凑,参数间保留 1 个空格
foo(a, b)
my_list = [1, 2, 3]

# 索引与函数名紧贴括号
items[0]
result = calculate_value(x)

# 默认参数/关键字参数等号两侧不加空格
def complex_func(arg1, default_val=10):
    return arg1 * default_val

complex_func(5, default_val=20)
1
2
3
4
5
6
7
8
9
10
11
12
13

不推荐

# 错误:括号边缘多余空格
foo( a, b )
items[ 0 ]

# 错误:逗号后缺少空格(过于拥挤)
foo(a,b)

# 错误:函数名与括号间、等号两侧多余空格
foo (a, b)
def func(arg = 5):
    pass
1
2
3
4
5
6
7
8
9
10
11

# 3.3 逗号、冒号的空格:后有空格,前不加

推荐

data = {"a": 1, "b": 2}
for i in range(1, 10):
    ...
1
2
3

不推荐

data = {"a":1,"b":2}
for i in range(1,10):
    ...
1
2
3

# 3.4 关键字参数 = 两边不加空格

这是很多人会写错的点:关键字参数不要写成 x = 1 这种。

推荐

connect(host="localhost", port=5432)
1

不推荐

connect(host = "localhost", port = 5432)
1

# 4. 命名规范(变量、函数、类、常量)

命名一旦统一,项目阅读成本会直线下降(其实主要是看起来确实更容易了!)

# 4.1 常见命名风格速记

在 Python 中,命名风格不仅是视觉上的统一,更是代码语义的一部分。通过不同的命名格式,开发者可以瞬间识别出一个标识符是类、函数还是常量,从而降低理解成本。

# 4.1.1 变量、函数与方法:lower_snake_case

这是 Python 中最常用的风格。所有字母小写,单词之间用下划线连接。

  • 设计逻辑:下划线增加了单词间的视觉距离,使得长命名在快速阅读时依然清晰。
  • 适用范围:普通变量、全局函数、类的方法(Method)、函数参数。

# 4.1.2 类:CapWords

每个单词的首字母大写,不使用下划线。

  • 设计逻辑:这种风格(也称大驼峰式)能将“类”(对象的蓝图)与“函数”(动作)在视觉上显著区分开。
  • 适用范围:异常类、基类、具体实现类。

# 4.1.3 模块级常量:UPPER_SNAKE_CASE

所有字母大写,单词之间用下划线连接。

  • 设计逻辑:全大写字母在代码中非常醒目,起到“警示”作用,提示开发者这是一个不应被修改的固定值。
  • 适用范围:配置参数、数学常数、固定阈值。

# 4.1.4 内部使用与冲突处理:下划线的妙用

  • 单前导下划线 _name:这是一种“弱内部使用”标识。它告诉其他开发者:“这是一个私有属性或内部工具函数,请不要在类或模块外部直接调用它。” 虽然 Python 语法不强制限制访问,但这是社区通用的尊重契约。
  • 单末尾下划线 name_:当你想用的变量名恰好是 Python 的保留关键字(如 class, list, type)时,在末尾加一个下划线是官方推荐的规避方案。

示例

# 常量:全局可见,不可修改
MAX_RETRY_COUNT = 5
DEFAULT_TIMEOUT = 30.0

# 类:首字母大写
class DataProcessor:
    def __init__(self):
        # 内部变量:提示外部不要直接访问
        self._is_initialized = False
    
    # 方法:小写加下划线
    def process_raw_data(self, data_list):
        pass

# 函数:小写加下划线
def fetch_user_by_id(user_id, class_="Standard"):
    # class_ 避免了与关键字 class 冲突
    pass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

命名风格对照表

类型 风格 示例
变量/函数/方法 小写下划线 calculate_total(), user_name
类 大驼峰 UserSession, HttpRequest
常量 大写下划线 API_KEY, MAX_THREADS
内部/私有 前导下划线 _internal_method(), _cache
避开关键字 末尾下划线 id_, type_, input_

# 4.2 避免 “l / O / I” 这种易混淆命名

例如 l(小写 L)在某些字体里像 1,O 像 0。

# 5. 注释与 Docstring(让代码“可维护”)

这部分是写给“未来的同事和未来的你”的🤓

# 5.1 注释写什么:解释“为什么”,不是复述“是什么”

推荐(解释原因/约束)

# 使用 UTC,避免夏令时导致的跨天 bug
expires_at = datetime.now(timezone.utc) + timedelta(hours=1)
1
2

不推荐(复述代码)

# 给 expires_at 加一小时
expires_at = datetime.now(timezone.utc) + timedelta(hours=1)
1
2

# 5.2 Docstring:给模块/类/函数写清楚“用途、参数、返回、异常”

PEP 8 更偏“形式与风格”,但日常你至少保持:

  • 一句话概述
  • 需要时补充参数/返回含义(团队有模板就跟模板)

推荐

def parse_user_id(raw: str) -> int:
    """Parse user id from a string.

    Args:
        raw: User id string, e.g. "123".

    Returns:
        Parsed user id as int.

    Raises:
        ValueError: If raw is not a valid integer.
    """
    return int(raw)
1
2
3
4
5
6
7
8
9
10
11
12
13

# 6. 逗号结尾(Trailing comma)与多行结构

这条很“工程化”,能显著减少 diff 噪音(主要是多人维护的团队合作项目)

# 6.1 多行列表/字典/参数建议保留尾逗号

推荐

items = [
    "apple",
    "banana",
    "orange",
]

config = {
    "host": "localhost",
    "port": 5432,
}
1
2
3
4
5
6
7
8
9
10

好处:以后新增一行不会改动上一行,Git diff 更干净。


# 7. 条件判断与 Pythonic 写法(PEP 8 常强调的“可读性”)

PEP 8 的精神是——可读性优先!

# 7.1 与 None 比较用 is / is not

推荐

if value is None:
    ...
1
2

不推荐

if value == None:
    ...
1
2

# 7.2 布尔判断别写 == True/False

推荐

if enabled:
    ...
if not enabled:
    ...
1
2
3
4

不推荐

if enabled == True:
    ...
if enabled == False:
    ...
1
2
3
4

# 7.3 成员判断用 in

推荐

if key in mapping:
    ...
1
2

# 8. 异常处理风格(高频且影响质量)

异常是对“可维护性”至关重要,玛卡巴卡就很少写try-catch捕获异常x(可能也是没有做过大项目导致的)

# 8.1 不要裸 except:

在 Python 中,except: 实际上等同于 except BaseException:。这种“全量捕获”会产生严重的副作用,导致程序失控或 Bug 被隐藏。

  • 屏蔽系统信号:它会捕获 KeyboardInterrupt(Ctrl+C)和 SystemExit。这意味着你无法通过常规手段强制停止一个死循环程序。
  • 掩盖逻辑错误:它会吞掉所有的异常,包括变量名拼错(NameError)或属性不存在(AttributeError)。这会让原本明显的逻辑 Bug 变得极难调试。
  • 最佳实践:始终指明具体的异常类型。如果确实需要捕获所有业务错误,请使用 except Exception:,它会跳过系统级的强制退出信号。

推荐

try:
    n = int(raw)
except ValueError:  # 精确捕获预期的转换错误
    n = 0

# 或者在需要捕获绝大多数错误时
try:
    do_something()
except Exception as e:  # 允许 Ctrl+C 退出,同时记录错误
    logging.error(f"Error: {e}")
1
2
3
4
5
6
7
8
9
10

不推荐

try:
    n = int(raw)
except:  # 裸捕获:Ctrl+C 失效,且会隐藏其他逻辑 Bug
    n = 0
1
2
3
4
捕获方式 捕获范围 评价
except: 所有(含系统信号) 禁止使用,会导致程序无法停止
except Exception: 所有业务异常 慎用,仅限顶层逻辑监控
except SpecificError: 仅指定的错误 推荐,最安全、最易于调试

# 8.2 异常别太宽;能具体就具体

在 Python 中,异常是分层级的。Exception 是几乎所有常规错误的“祖先”。如果你捕获了 Exception,就意味着你同时捕获了 IndexError、KeyError、TypeError、NameError 等几十种完全不同的错误。

# 8.2.1. 避免“张冠李戴”的错误处理

每种异常通常对应不同的解决办法。

  • 如果是 FileNotFoundError,你可能想提示用户检查路径。
  • 如果是 PermissionError,你可能想提示用户提升权限。
  • 如果你统一捕获 Exception 并提示“文件出错”,当程序其实是因为“内存溢出”或“变量名写错”而崩溃时,这个提示会严重误导用户。

# 8.2.2. 保护真正的 Bug 不被掩盖

这是最危险的一点。请看下面的例子:

# 糟糕的写法:范围太宽
try:
    user = get_user_info()
    age = user["age"] + 1  # 如果 user 字典里没有 "age",会报 KeyError
except Exception:
    age = 0  # 你本意是想处理 KeyError
1
2
3
4
5
6

隐藏的危机:如果 get_user_info() 函数内部因为某个逻辑写错报了 NameError,或者 user["age"] 的值是字符串导致加法报了 TypeError,这些真正的代码 Bug 都会被 except Exception 默默吞掉,并给 age 赋值为 0。程序会继续带着错误的数据运行,直到在更远的地方引发更难排查的崩溃。

什么时候可以用 Exception?

  1. 顶层监控(Global Catch-all):在 Web 框架或大型系统的最外层,为了防止一个小的子功能报错导致整个服务器宕机,会捕获 Exception。
  2. 记录并重新抛出:你想在程序崩溃前把错误堆栈记入日志,记录完后再用 raise 把错误原样抛出。

# 9. 字符串引号、格式化与可读性

这块更多是“统一风格”,不过也看自己的习惯咯

# 9.1 单引号/双引号:项目内一致即可

PEP 8 不强制单/双引号,但强调一致性。

# 9.2 字符串拼接优先用 f-string / .format,避免 + 乱拼

推荐

name = "Alice"
msg = f"Hello, {name}"
1
2

不推荐(大量 + 会变难读)

msg = "Hello, " + name + "!"
1

# 10. 一些高频需要记住的PEP 8 规范

这一块给你做总结页/背诵页很方便:

  • 缩进:4 空格;不要混 Tab
  • 行宽:代码 79,注释/docstring 72
  • 换行:优先用括号隐式换行,不用 \
  • 空行:顶层函数/类 2 行;类方法之间 1 行
  • 导入:标准库 → 第三方 → 本地;组间空行;避免 import *
  • 空格:运算符两边加空格;关键字参数 = 不加空格
  • 命名:函数/变量 snake_case;类 CapWords;常量 UPPER_CASE
  • 判断:is None;不用 == True/False
  • 异常:别裸 except:;尽量捕获具体异常
  • 多行容器:建议保留尾逗号减少 diff 噪音
上次更新: 2026/04/30, 17:04:36
最近更新
01
快乐小狗狂喜!(小声版)
05-01
02
乌黑的眼睛
04-30
03
人总在接近幸福时倍感幸福
04-29
更多文章>
Theme by Vdoing | Copyright © 2026-2026 玛卡巴卡 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式