Python代码审查与修复助手

0 浏览
0 试用
0 购买
Nov 4, 2025更新

本提示词专为Python开发者设计,提供专业级的代码审查与修复服务。通过深度分析代码结构,精准识别潜在错误、风格不一致和性能瓶颈问题,并给出具体修复建议和优化方案。具备多场景适配能力,支持从基础语法检查到复杂逻辑优化的全流程代码质量提升,帮助开发者快速提升代码健壮性和可维护性。

代码审查摘要

该代码包含多项高危安全问题,主要集中在命令执行、数据库访问、密码处理、反序列化及临时文件使用等环节。问题可导致远程命令执行、SQL注入、任意代码执行、凭证泄露、权限提升与信息泄露等严重风险。以下提供分级问题清单、可操作修复方案与一份重构示例代码。


详细问题列表(按严重程度分类)

  • 严重

    1. 命令注入
      • 位置:run_backup(cmd) 使用 subprocess.run(cmd, shell=True)
      • 问题:用户输入直接进入 shell,允许执行任意命令
      • 影响:远程命令执行(RCE)
    2. SQL 注入
      • 位置:load_user 中使用 f-string 拼接 SQL
      • 问题:未参数化查询,name/pwd 可注入
      • 影响:认证绕过、数据泄露或破坏
    3. 不安全反序列化
      • 位置:handle_payload 使用 pickle.loads
      • 问题:反序列化任意不受信数据
      • 影响:任意代码执行
  • 高 4) 弱密码哈希与敏感信息泄露

    • 位置:check_password 使用 MD5;main 打印 token
    • 问题:MD5 不适用于口令;将哈希作为 token 输出
    • 影响:凭证泄露、离线暴力破解
    1. 临时文件路径可预测
      • 位置:write_temp 使用 /tmp/tmp_{pid}.txt
      • 问题:可被抢占/软链接攻击,非原子创建
      • 影响:信息泄露、文件覆盖、权限提升
    2. 外部进程缺少约束
      • 位置:run_backup 未设置 check/timeout/绝对路径/白名单
      • 影响:僵死进程、执行非预期程序、资源耗尽
  • 中 7) 异常被吞掉

    • 位置:main 中 except Exception as e: pass
    • 问题:错误无法追踪,影藏异常
    • 影响:可观测性差,问题难以定位
    1. 明文回显密码输入
      • 位置:main 使用 input 读取 pwd
      • 问题:终端回显口令
      • 影响:旁观者可见,泄露风险
    2. 数据库资源管理与风格
      • 位置:load_user 手动打开/关闭连接与游标
      • 问题:缺少 with 语法上下文管理;错误处理缺失
      • 影响:异常时资源释放不及时、代码可读性差
  • 低 10) 代码风格(PEP8) - 位置:import os, sqlite3, ... - 问题:多库同行导入,不符合 PEP8;部分命名不具语义 - 影响:可读性与一致性降低 11) 信息输出 - 位置:print('user:', user) - 问题:原样打印数据库记录 - 影响:潜在信息泄露(在日志/控制台)


具体修复建议

  • 命令执行

    • 禁止 shell=True。使用参数列表调用固定的受信程序,采用白名单策略。
    • 使用绝对路径而非依赖 PATH。
    • 设置 check=True、timeout,并捕获输出以便审计。
    • 限制用户可选动作(如 “full”“inc” 两类备份),而非自由命令行。
  • 数据库访问与认证

    • 全面改用参数化查询:cur.execute("SELECT ... FROM users WHERE name=? AND pwd=?", (name, pwd))
    • 口令存储改造:存储基于 PBKDF2/Argon2 的强哈希(带盐)。推荐:
      • 标准库:hashlib.pbkdf2_hmac('sha256', ..., iterations>=200000) + 16字节随机盐(secrets.token_bytes)
      • 常量时间比较:hmac.compare_digest
    • 认证流程:先按用户名查询取出 salt 与 hash,再校验密码,严禁 WHERE pwd=... 的明文比对。
    • 使用 with 管理连接与游标;设置 conn.row_factory=sqlite3.Row 提升可读性。
  • 反序列化

    • 禁止对不受信数据使用 pickle。若需结构化数据,使用 json.loads 或自定义安全解析器。
    • 对输入大小与类型进行约束并校验。
  • 临时文件

    • 使用 tempfile.NamedTemporaryFile(delete=False) 或 tempfile.mkstemp 安全创建;避免可预测文件名。
    • 需要跨进程读取时,保留文件名但保证原子创建与 0600 权限。
  • 异常与日志

    • 不要吞异常。记录到日志(logging),返回或提示不包含敏感细节的错误信息。
    • 为外部进程、数据库操作、解析流程添加具体异常处理与告警。
  • 输入与输出

    • 使用 getpass.getpass 读取密码,避免回显。
    • 不打印 token 或敏感字段到标准输出/日志。
    • 对输入设置长度上限与格式校验(如 payload 最大长度)。
  • 代码风格与可维护性

    • 每行一个 import;函数与变量命名具备语义。
    • 为安全关键函数添加文档字符串,解释约束与预期输入。
    • 在类型敏感处(如函数返回值)可加上类型注解以提升可维护性。

优化方案

  • 安全基线

    • 为 SQLite 文件设置严格文件权限(仅运行用户可读写)。
    • 数据库 schema 增加唯一索引(users.name UNIQUE)与必要约束。
    • 统一日志格式与等级;为安全事件标注审计字段。
  • 健壮性

    • 限制外部进程资源(timeout 已建议);必要时在上层加入任务队列与并发限制。
    • 为输入数据添加长度阈值(如命令参数、payload 不超过固定大小)。
  • 可测试性

    • 为密码哈希与验证、输入解析、SQL 查询添加单元测试与集成测试。
    • 使用临时数据库与测试替身(mocks)验证异常路径与边界条件。

重构代码示例(安全基线实现示例)

说明:

  • 示例将“备份命令”改为固定动作白名单,拒绝任意命令。
  • 认证改为“按用户名查 salt/hash -> 本地 PBKDF2 校验”的安全流程。需要数据库包含列:users(name UNIQUE, pwd_hash TEXT, pwd_salt TEXT, role TEXT, ...)。生产中需进行数据迁移。
  • 反序列化改为 JSON。
  • 临时文件使用 tempfile 安全创建。
  • 添加基本日志与异常处理。
import json
import hmac
import hashlib
import logging
import secrets
import shlex
import sqlite3
import subprocess
import tempfile
from getpass import getpass
from typing import Optional, Tuple

# 日志基础配置(生产环境按需要调整 handler/formatter)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 仅允许声明好的备份动作,对应固定可执行文件与参数
ALLOWED_BACKUP_ACTIONS = {
    "full": ["/usr/local/bin/safe_backup", "--full"],
    "inc": ["/usr/local/bin/safe_backup", "--incremental"],
}


def run_backup(choice: str) -> None:
    """
    仅允许调用白名单动作,禁用 shell。
    """
    action = choice.strip().lower()
    cmd = ALLOWED_BACKUP_ACTIONS.get(action)
    if not cmd:
        raise ValueError("invalid backup action")
    # 绝对路径 + check + timeout,禁用 shell
    result = subprocess.run(cmd, check=True, timeout=600, capture_output=True, text=True)
    logger.info("backup finished: %s", result.stdout.strip())


def pbkdf2_hash_password(password: str, *, iterations: int = 200_000) -> Tuple[str, str, int]:
    """
    基于 PBKDF2-SHA256 的口令派生;返回 (hex_hash, hex_salt, iterations)
    """
    salt = secrets.token_bytes(16)
    dk = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"), salt, iterations)
    return dk.hex(), salt.hex(), iterations


def pbkdf2_verify_password(password: str, hex_hash: str, hex_salt: str, iterations: int) -> bool:
    """
    常量时间比较,验证口令
    """
    salt = bytes.fromhex(hex_salt)
    dk = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"), salt, iterations)
    return hmac.compare_digest(dk.hex(), hex_hash)


def load_user(name: str, password: str) -> Optional[Tuple[int, str]]:
    """
    安全认证流程:
    1) 参数化查询按用户名取回 hash/salt/迭代
    2) 本地验证密码
    3) 返回 (id, role)
    需数据库列:id, name, role, pwd_hash, pwd_salt, pwd_iter
    """
    sql = "SELECT id, role, pwd_hash, pwd_salt, pwd_iter FROM users WHERE name = ?"
    try:
        with sqlite3.connect("users.db", timeout=5) as conn:
            conn.row_factory = sqlite3.Row
            row = conn.execute(sql, (name,)).fetchone()
    except sqlite3.Error as e:
        logger.exception("database error")
        raise

    if not row:
        return None

    pwd_hash = row["pwd_hash"]
    pwd_salt = row["pwd_salt"]
    iterations = int(row["pwd_iter"])

    if not pbkdf2_verify_password(password, pwd_hash, pwd_salt, iterations):
        return None

    return row["id"], row["role"]


def handle_payload_json(s: str):
    """
    使用 JSON 解析不受信数据,并限制大小。
    """
    if len(s) > 10_000:  # 上限防止资源滥用,根据业务调优
        raise ValueError("payload too large")
    try:
        return json.loads(s)
    except json.JSONDecodeError as e:
        raise ValueError("invalid JSON payload") from e


def write_temp(content: str) -> str:
    """
    安全创建临时文件(0600),避免可预测路径与竞态。
    """
    with tempfile.NamedTemporaryFile(mode="w", delete=False, encoding="utf-8", prefix="app_", suffix=".txt") as f:
        f.write(content)
        return f.name


def main():
    try:
        # 仅允许白名单备份动作(例如:full 或 inc)
        backup_choice = input("backup action [full/inc]> ")
        run_backup(backup_choice)

        name = input("name: ")
        pwd = getpass("pwd: ")

        user = load_user(name, pwd)
        if user is None:
            print("authentication failed")
            return
        print("user:", {"id": user[0], "role": user[1]})  # 输出脱敏/最小化

        payload_text = input("payload (json): ")
        data = handle_payload_json(payload_text)
        logger.info("payload accepted: type=%s", type(data).__name__)

        path = write_temp("ok")
        logger.info("wrote temp file: %s", path)

        # 如果需要会话 token,请使用随机值而非密码派生
        session_token = secrets.token_urlsafe(32)
        logger.info("session started")
        # 不要将 token 打印到终端或日志。这里只示例生成方式,不输出。

    except subprocess.TimeoutExpired:
        logger.error("backup timeout")
    except subprocess.CalledProcessError:
        logger.error("backup failed")
    except Exception:
        # 记录日志,避免向用户暴露敏感细节
        logger.exception("unexpected error")
        print("internal error")

if __name__ == "__main__":
    main()

迁移与落地建议(口令哈希)

  • 为 users 表新增列:pwd_hash TEXT, pwd_salt TEXT, pwd_iter INTEGER
  • 为现有用户执行一次迁移:读取明文或过渡哈希,使用 PBKDF2 生成新哈希与盐,写回新列;完成后清空旧的明文字段
  • 新用户注册/修改密码时:调用 pbkdf2_hash_password 存储三元组

以上修改聚焦安全性与可维护性,避免了命令注入、SQL 注入与不安全反序列化等核心风险,并对口令保护、临时文件与可观测性进行了系统强化。

代码审查摘要

  • 发现多处性能瓶颈:循环内重复编译正则、使用列表去重与计数导致 O(n^2)、手写冒泡排序 O(n^2)、整文件读入导致高内存占用、重复遍历日志文件两次。
  • 发现1处明确逻辑缺陷:count_errors 中 v += 1 未写回,计数失效。
  • 解析逻辑不一致:aggregate 用正则但不strip,parse_error 用 split 并 strip,去重与计数口径不一致,可能造成重复与统计不一致。
  • 风格与可维护性问题:缺少预编译正则的模块常量、缺少类型注解与文档字符串、I/O 未显式指定编码与错误策略。

详细问题列表(按严重程度分类)

  1. 逻辑缺陷:count_errors 未正确累加

    • 位置:count_errors 中 for k, v in counts 循环,使用 v += 1 但未写回 counts;且 counts 元素为 [err, int],解包为 k, v 后对 v 的修改不会反映到原列表。
    • 影响:错误计数不增长或重复插入,导致统计不正确;同时带来不必要的 O(n^2) 时间开销。
  2. 性能问题:正则在内层循环重复编译

    • 位置:aggregate 中 re.compile(r'ERROR:(.+)') 位于每行处理内部。
    • 影响:大量正则编译开销,尤其在大日志文件下明显。
  3. 性能问题:去重使用列表 in 判断

    • 位置:aggregate 中 if m.group(1) not in errors 使用列表去重。
    • 影响:整体退化为 O(n^2)。
  4. 性能问题:手写冒泡排序

    • 位置:aggregate 尾部双层循环排序。
    • 影响:O(n^2) 排序,且 Python 内置排序更快且稳定。
  5. 内存与I/O问题:一次性读入整文件

    • 位置:read_lines 使用 f.readlines()。
    • 影响:大文件高内存占用,降低处理吞吐。
  6. 解析口径不一致导致结果不一致

    • 位置:parse_error 使用 split 并 strip;aggregate 使用正则提取但未 strip。
    • 影响:unique 与 count 的结果可能不一致,例如 "ERROR: foo" 与 "ERROR: foo" 被视为不同。

  1. 代码重复扫描日志文件

    • 位置:aggregate 与 count_errors 各自遍历 paths。
    • 影响:I/O 成本翻倍;可在单次遍历中同时完成去重与计数。
  2. 取 Top N 的方式低效

    • 位置:main 中对 counts 全量排序再切片。
    • 影响:对大量错误种类时不必要的 O(m log m),可用 nlargest 或 Counter.most_common(n)。
  3. 解析正则未显式处理空白

    • 位置:aggregate 使用 r'ERROR:(.+)',可能包含前导空格。
    • 影响:包含不必要的空白,影响去重与统计的一致性。
  4. 文件编码与解码错误未控制

    • 位置:open(path) 未指定 encoding 与 errors。
    • 影响:不同环境可能抛出解码错误,影响处理稳定性。

  1. 索引式循环可用直接迭代

    • 位置:aggregate 中 for i in range(0, len(lines))。
    • 影响:可读性与微小性能损失。
  2. 缺少类型注解与文档字符串

    • 位置:全局。
    • 影响:可维护性与静态检查能力下降。
  3. 未统一常量与命名规范

    • 位置:正则模式应上移为模块常量(PEP 8)。

具体修复建议

  • 统一错误解析口径:使用预编译正则 ERROR_RE = re.compile(r'ERROR:\s*(.+)') 并在 parse_error/aggregate 中统一 strip。
  • 改用流式读取:read_lines 返回生成器,逐行处理,指定 encoding='utf-8' 与 errors='ignore'(或 'replace')。
  • 使用 set 去重、collections.Counter 计数,整体时间复杂度降至 O(N)。
  • 使用内置排序 sorted(errors_set, key=str.lower) 替换手写冒泡。
  • 使用 Counter.most_common(n) 或 heapq.nlargest 获取 Top N,避免全量排序。
  • 修复 count_errors 的计数逻辑,改为字典或 Counter;保持返回格式兼容需要时再转换为 list。
  • 可选:合并扫描,将去重与计数在一次遍历中完成,降低 I/O。

优化方案

  • 算法与复杂度
    • 旧方案:去重 O(N^2)、排序 O(M^2)、计数 O(N^2)、两次 I/O 扫描;整体时间上界接近 O(N^2)。
    • 新方案:单次扫描 O(N),去重用 set O(1) 均摊,计数用 Counter O(1) 均摊;排序仅用于最终 unique 展示 O(M log M);Top N 用 most_common(n) 为 O(M + n log M) 或近似 O(M)。
  • 内存
    • 旧方案:readlines() 按文件大小占用内存。
    • 新方案:逐行流式处理,常量级内存开销,加上 set 与 Counter 的规模。
  • I/O
    • 旧方案:重复遍历文件两次。
    • 新方案:可选合并扫描为一次,或保留两个函数但内部皆为流式读取。

重构代码示例

说明:

  • 保持原有函数名与主流程基本兼容。
  • 统一解析口径,修复计数逻辑,替换低效结构。
  • 提供一个可选的单次扫描函数以进一步减少 I/O。
import re
from collections import Counter
from typing import Iterable, List, Optional, Tuple

# 预编译正则:匹配 "ERROR:" 后的有效信息,忽略其后空白
ERROR_RE = re.compile(r'ERROR:\s*(.+)')

def read_lines(path: str, encoding: str = 'utf-8') -> Iterable[str]:
    """
    流式读取文件,避免一次性读入大文件。
    """
    # 若日志存在非 UTF-8 字符,忽略解码错误以保证处理不中断
    with open(path, encoding=encoding, errors='ignore') as f:
        for line in f:
            yield line

def parse_error(line: str) -> Optional[str]:
    """
    从一行文本中解析错误信息。返回去除首尾空白的错误内容。
    """
    m = ERROR_RE.search(line)
    return m.group(1).strip() if m else None

def aggregate(paths: Iterable[str]) -> List[str]:
    """
    返回按不区分大小写排序的唯一错误列表。
    时间复杂度:O(N) 去重 + O(M log M) 排序(M为错误种类数)
    """
    errors_set = set()
    for p in paths:
        for line in read_lines(p):
            err = parse_error(line)
            if err:
                errors_set.add(err)
    # 使用内置排序,按大小写不敏感排序,行为与原代码一致
    return sorted(errors_set, key=str.lower)

def count_errors(paths: Iterable[str]) -> List[List[object]]:
    """
    统计每类错误出现次数。
    返回格式与原代码兼容:[[error, count], ...]
    时间复杂度:O(N)
    """
    counter = Counter()
    for p in paths:
        for line in read_lines(p):
            err = parse_error(line)
            if err:
                counter[err] += 1
    # 保持原返回格式(list[list]),便于与主程序兼容
    return [[err, cnt] for err, cnt in counter.items()]

# 可选:单次扫描同时完成去重与计数,减少 I/O
def scan_errors(paths: Iterable[str]) -> Tuple[List[str], Counter]:
    """
    单次遍历所有文件,返回:
    - unique_errors: 按大小写不敏感排序的唯一错误列表
    - counter: 错误计数 Counter
    """
    unique_set = set()
    counter = Counter()
    for p in paths:
        for line in read_lines(p):
            err = parse_error(line)
            if err:
                unique_set.add(err)
                counter[err] += 1
    unique_errors = sorted(unique_set, key=str.lower)
    return unique_errors, counter

def main() -> None:
    paths = ['app1.log', 'app2.log']

    # 方案A:与原主流程保持一致的调用方式
    unique = aggregate(paths)
    counts = count_errors(paths)
    print('unique', len(unique))
    # 更高效的 TOP N 获取方式(将 list 转回 Counter 使用 most_common)
    top = Counter({k: v for k, v in counts}).most_common(5)
    print('top', top)

    # 方案B:一次扫描完成(如需进一步降低 I/O)
    # unique2, counter2 = scan_errors(paths)
    # print('unique', len(unique2))
    # print('top', counter2.most_common(5))

if __name__ == '__main__':
    main()

说明与验证要点:

  • 解析统一:parse_error 与 aggregate 使用相同的正则与 strip,避免同一错误因空白差异被视为不同。
  • 性能改进:
    • 去重:由列表 O(n^2) 改为 set O(n)。
    • 计数:由列表查找 O(n^2) 改为 Counter O(n)。
    • 排序:由手写 O(n^2) 改为内置 Timsort O(n log n)。
    • 正则编译移动至模块级常量,仅编译一次。
    • I/O:流式读取,避免整文件占用内存。
    • Top N:使用 Counter.most_common(5),避免全量排序。
  • 接口兼容:count_errors 返回值仍为二元列表,兼容原 sorted(counts, key=lambda x: -x[1]) 用法;示例中演示了更高效的转换计 Top N 的做法。

建议的进一步测试与验证:

  • 使用包含大文件与混合编码的日志进行性能与健壮性验证。
  • 验证不同空白与大小写的错误消息去重与排序是否符合预期(例如 "ERROR: Foo" 与 "ERROR: Foo" 视为同一条)。如需大小写不敏感的去重,可在 parse_error 后统一标准化为同一大小写并保留原始大小写映射,这将改变行为,需按需求确认后实施。

代码审查摘要

  • 完成对输入代码的结构解析、语法检查、风格评估、逻辑缺陷识别、性能分析与安全性评估。
  • 发现多处可维护性与健壮性问题,包括可变默认参数、浮点货币计算、异常处理过宽、命名不规范、不可达代码、文件读取与缓存设计不严谨等。
  • 提供了具体修复建议与经过验证的重构示例,确保符合PEP8规范与常见最佳实践。

详细问题列表(按严重程度分类)

严重问题

  1. 可变默认参数
    • order.__init__(items=[])load_data(fp, cache={}) 使用可变默认值,会导致跨调用共享状态。
  2. 货币计算使用浮点数
    • calcTotalapply_discount 使用 float 进行金额与税费计算,存在精度与舍入风险。
  3. 异常处理过宽
    • get_userId 使用裸 except,会吞掉所有异常,不利于定位与安全。
  4. 不可达代码
    • apply_discountreturn 后存在 print('discount applied'),永不执行。
  5. 逻辑分支无效/冗余
    • apply_discountif total > 1000else 分支计算公式一致(rate + 0.0rate 等价),阈值判断不起作用。
  6. 命名与风格不符合PEP8
    • 类名应使用 CapWordsorder 应为 Order)。
    • 方法名应使用小写加下划线(calcTotalget_userId)。
    • 属性命名不一致(Items 应为 items)。
  7. 数据模型不明确
    • add 使用字典键 'n'/'p'/'q' 缩写,可读性与可维护性较差。

一般问题

  1. 使用“魔法常量”
    • 折扣上限 cap=9999999 与阈值 1000 未抽象为常量或文档说明。
  2. 时间字段类型不严谨
    • created_at 使用字符串,建议使用 datetime
  3. 未使用的属性
    • _cache_total 从未被读取或更新。
  4. 文件读取编码未指定与错误未处理
    • load_data 未指定编码与异常处理;缓存策略依赖参数默认值,存在隐性共享。

轻微问题

  1. 循环累加可用内置函数优化
    • total = total + it['p'] * it['q'] 可用 sum(...) 简化。
  2. 注释与命名不一致
    • 中英文注释混用且未系统说明设计意图。

具体修复建议

  • 避免可变默认参数:
    • items=[]cache={} 改为 None,在函数体内初始化。
  • 金额计算使用 decimal.Decimal 并统一舍入规则:
    • 设置统一的 money() 函数进行“两位小数、四舍五入”。
  • 异常处理收窄并显式类型检查:
    • get_userId 捕获 ValueErrorTypeError,避免裸 except
  • 移除不可达代码:
    • 删除 apply_discount 中的 print 或移至返回前并改为日志。
  • 统一命名风格至PEP8:
    • 类名 Order、方法名 calc_totalget_user_id、属性名 items
  • 明确数据模型:
    • 使用 dataclass 定义 OrderItem,字段命名完整,如 name/price/qty
  • 抽象魔法常量为命名常量:
    • TAX_RATE 保留;为折扣上限、阈值等定义常量或参数。
  • 文件读取改进:
    • 指定编码 utf-8;可选传入缓存对象而非默认共享;必要时添加异常处理。
  • 删除未使用属性或完善缓存策略:
    • 如不实现缓存,总计 _cache_total 可移除;如要缓存,需在 add 时失效并在计算后更新。
  • 文档化参数含义:
    • 明确折扣费率支持“小数(0.1)或百分数(10)”,并统一归一化。

性能瓶颈分析

  • 当前数据规模下主要为O(n)遍历,无明显性能瓶颈。
  • 微优化:
    • 使用 sum 内生成式代替循环累加。
    • 文件缓存可用 functools.lru_cache 或模块级缓存替代参数缓存,避免重复IO。

优化方案

  • 引入类型注解与文档字符串,提升可读性与可维护性。
  • 金额计算统一使用 Decimal 与量化,避免浮点误差。
  • 采用 dataclasses 管理订单项,减少字典键错误风险。
  • 可选:将折扣逻辑封装为可测试的纯函数;引入日志取代 print

重构代码示例

以下示例实现上述修复与优化建议,保持原有业务行为(含保留负总额返回0的逻辑),并符合PEP8与常见最佳实践。

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from decimal import Decimal, ROUND_HALF_UP, getcontext
from typing import Any, Dict, Iterable, Optional

# 设置Decimal精度
getcontext().prec = 28

# 常量定义
TAX_RATE = Decimal("0.13")
DEFAULT_DISCOUNT_RATE = Decimal("0.05")

def to_decimal(value: Any) -> Decimal:
    """
    将输入转换为Decimal。使用str避免float的二进制表示误差。
    """
    return Decimal(str(value))

def money(value: Decimal) -> Decimal:
    """
    统一金额量化到两位小数,四舍五入。
    """
    return value.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

@dataclass(frozen=True)
class OrderItem:
    name: str
    price: Decimal
    qty: int = 1

class Order:
    def __init__(
        self,
        items: Optional[list[OrderItem]] = None,
        created_at: Optional[datetime] = None,
    ) -> None:
        # 避免可变默认参数共享
        self.items: list[OrderItem] = items[:] if items else []
        # 使用datetime而非字符串
        self.created_at: datetime = created_at or datetime.now()

    def add(self, name: str, price: float | str | Decimal, qty: int = 1) -> None:
        """
        添加订单项,价格统一转换为Decimal。
        """
        self.items.append(OrderItem(name=name, price=to_decimal(price), qty=qty))

    def calc_total(self, tax: bool = True) -> Decimal:
        """
        计算订单总价,可选是否包含税费。
        """
        subtotal = sum(item.price * item.qty for item in self.items)
        if tax:
            subtotal *= (Decimal("1") + TAX_RATE)
        return money(subtotal)

def normalize_rate(rate: float | Decimal) -> Decimal:
    """
    归一化折扣率:
    - 输入>1视为百分比(如10->0.10)
    - 输入<=1视为小数(如0.1)
    - 限定到[0, 1]区间
    """
    r = to_decimal(rate)
    if r > 1:
        r = r / Decimal("100")
    if r < 0:
        r = Decimal("0")
    if r > 1:
        r = Decimal("1")
    return r

def apply_discount(
    total: float | Decimal,
    rate: float | Decimal = DEFAULT_DISCOUNT_RATE,
    cap: Optional[float | Decimal] = None,
) -> Decimal:
    """
    应用折扣:
    - total<0 时返回0(保持原逻辑)
    - 支持小数或百分比折扣率
    - 可选折扣封顶cap
    """
    t = to_decimal(total)
    if t < 0:
        return Decimal("0.00")

    r = normalize_rate(rate)
    discount = t * r

    if cap is not None:
        discount = min(discount, to_decimal(cap))

    return money(t - discount)

def load_data(fp: str, cache: Optional[Dict[str, list[str]]] = None) -> list[str]:
    """
    读取文件内容(逐行),支持外部传入缓存。
    """
    cache = cache or {}
    if fp in cache:
        return cache[fp]

    # 指定编码,避免平台差异
    with open(fp, encoding="utf-8") as f:
        data = f.read().splitlines()

    cache[fp] = data
    return data

def get_user_id(user: Dict[str, Any]) -> Optional[int]:
    """
    尝试从字典中读取id并转换为int,异常范围收窄。
    """
    value = user.get("id")
    try:
        return int(value) if value is not None else None
    except (ValueError, TypeError):
        return None

def process(orders: Iterable[Order]) -> Decimal:
    """
    处理订单集合,计算总金额并应用折扣。
    """
    total = Decimal("0")
    for o in orders:
        ot = o.calc_total(tax=True)
        total += apply_discount(ot, rate=Decimal("0.10"), cap=Decimal("500"))
    return money(total)

def main() -> None:
    o = Order()
    o.add("USB", "19.90", 2)
    o.add("Book", "45.00", 1)
    print(process([o]))

if __name__ == "__main__":
    main()

说明:

  • 将金额相关运算全面切换为 Decimal,并通过 money() 保证输出两位小数的四舍五入。
  • 删除 apply_discount 的无效分支与不可达代码,保留原逻辑中“负总额返回0”的行为。
  • 避免可变默认参数带来的状态泄漏。
  • 统一命名风格与类型注解,提高可读性、可维护性与静态分析友好性。
  • OrderItem 使用数据类,减少键名错误与提升结构清晰度。
  • 文件读取指定编码;缓存通过参数传入,避免隐藏共享状态。

此外可选改进(不改变当前行为):

  • 如果需要全局缓存文件读取,可考虑使用 functools.lru_cache 包装纯函数读取逻辑,或模块级缓存字典,并提供明确的失效策略。
  • 为税率、折扣上限、阈值等策略参数提供配置入口或说明文档。

示例详情

解决的问题

以“Python代码审查与修复助手”为核心,面向企业与个人开发者,打造一款即插即用的专业审查工具,帮助用户在编码、提交、合并与发布各环节快速提升代码质量与效率。核心目标:

  • 让 AI 扮演资深代码审查专家,输出清晰、可执行的改进建议与重构示例
  • 以结果导向的报告形式,优先级标注问题,帮助用户快速定位并修复
  • 覆盖语法、逻辑、风格、运行效率、可维护性与安全性等全链路质量要点
  • 将“发现问题—给出方案—示例重构”整合为一体,缩短修复周期,减少返工
  • 支持多种实战场景:团队审查、开源贡献、教学评作、技术面试、遗留代码整治
  • 提供可持续价值:降低线上风险、提升交付稳定性、加快合并与发布节奏
  • 通过试用版快速体验审查能力,进阶版本解锁团队协作与更深度优化能力,促进付费转化

适用用户

后端Python开发工程师

在迭代中快速自检代码与风格,一次扫描定位逻辑缺陷与异常边界,拿到可直接应用的修复片段,缩短评审与回归时间。

数据工程师与数据科学家

审查ETL脚本与数据处理流程,优化高耗时环节与内存使用,减少任务失败与重跑,保障数据产出按时稳定。

技术负责人与架构师

统一编码标准与审查口径,批量生成模块级问题清单和优先级,制定渐进式重构计划,持续压降技术债务。

特征总结

覆盖从语法检查到逻辑优化的全流程审查,一键生成清晰报告,帮助团队快速定位高优先级问题
自动对照PEP8风格指南整理命名与注释,统一代码格式,降低评审沟通成本与维护成本
智能识别潜在异常与边界条件遗漏,给出可直接粘贴的修复片段,减少线上故障与回滚风险
从算法与数据结构角度定位性能瓶颈,提供替代方案与复杂度提示,显著加快关键路径
一键生成按严重程度分组的问题清单,配套修复优先级与时间预估,便于排期与跨组协作
支持多场景适配:企业审查、开源贡献、面试作业与教学练习,统一质量标准与产出格式
自动标注问题位置与成因说明,结合示例代码讲解修改思路,帮助新人快速掌握最佳实践
提供轻量化重构建议与命名优化指南,逐步提升可读性与可维护性,长期降低技术债务
结合团队现状定制检查项与输出模板,适配不同分支策略与发布节奏,快速融入现有流程

如何使用购买的提示词模板

1. 直接在外部 Chat 应用中使用

将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。

2. 发布为 API 接口调用

把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。

3. 在 MCP Client 中配置使用

在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。

AI 提示词价格
¥20.00元
先用后买,用好了再付款,超安全!

您购买后可以获得什么

获得完整提示词模板
- 共 526 tokens
- 2 个可调节参数
{ Python代码 } { 审查目标 }
获得社区贡献内容的使用权
- 精选社区优质案例,助您快速上手提示词
限时免费

不要错过!

免费获取高级提示词-优惠即将到期

17
:
23
小时
:
59
分钟
:
59