You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

忽略注释、格式、函数名时如何判断两个Python函数源码是否相等

解决方案

核心思路

CPython 没有公开的开关可以关闭字节码生成阶段的死代码删除优化,基于 __code__.co_code 的判断路径无法满足需求。
你需要的是源码层面的标准化对比,基于抽象语法树(AST)实现即可:AST 由源码直接解析生成,不会受字节码优化影响,天然过滤注释、无关空格、文档字符串,同时完整保留所有源码层面的语法节点,哪怕是不可达的死代码。

实现代码

import inspect
import ast
import hashlib
from typing import Callable

def get_func_standard_hash(func: Callable) -> str:
    # 获取函数的原始源码
    source_code = inspect.getsource(func)
    # 将源码解析为 AST 节点
    tree = ast.parse(source_code)
    func_def = tree.body[0]
    # 统一替换函数名,忽略函数名差异
    func_def.name = "_placeholder_"
    # 移除函数的文档字符串
    if (
        len(func_def.body) > 0
        and isinstance(func_def.body[0], ast.Expr)
        and isinstance(func_def.body[0].value, ast.Constant)
    ):
        func_def.body.pop(0)
    # 将 AST 转换为无格式差异的标准化字节串
    normalized_content = ast.dump(func_def, indent=None, annotate_fields=False).encode("utf-8")
    # 计算并返回哈希值
    return hashlib.sha256(normalized_content).hexdigest()

效果验证

用例1:逻辑等价但源码包含死代码

def f(a, b):
    return a
    return a

def g(a, b):
    return a

print(get_func_standard_hash(f) == get_func_standard_hash(g))
# 输出:False,符合预期

用例2:源码完全一致的两个不同函数

def f(a, b):
    return a

def g(a, b):
    return a

print(get_func_standard_hash(f) == get_func_standard_hash(g))
# 输出:True,符合预期

用例3:空格、注释、文档字符串不同的等价函数

def   f(  a , b):
    """Good job... hm, it was a good day..."""
    return a
    # NICE


def g(a,    b  ):
    #    HELLLOOOOOOO
    return         a

print(get_func_standard_hash(f) == get_func_standard_hash(g))
# 输出:True,符合预期

注意事项

  • 该方案依赖函数源码可被读取,不适用于无对应源码的已编译 .pyc 场景。
  • 如果函数被装饰器包裹,可先用 inspect.unwrap(func) 拿到原始函数后再计算哈希。

内容的提问来源于stack exchange,提问作者nbro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 13:24:02