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

如何检测Python类是否调用指定self.foo()方法以校验登记字典完整性

检测类是否调用指定方法的实现方案

完全可以实现,你可以用Python自带的ast(抽象语法树)模块静态解析类方法源码,配合继承关系校验完成检测,因为你已经明确排除了getattr等动态属性访问场景,所有目标调用都以self.foo()形式实现,该方案准确率可以满足需求。

实现逻辑

  • 先遍历所有继承自Human的候选类,按类的MRO(方法解析顺序)查找所有未被子类重写的方法
  • 解析每个方法的源码为AST节点,遍历节点查找self.foo()形式的调用
  • 只要在任意未被重写的方法中找到对应调用,就判定该类符合登记要求

示例实现代码

import ast
import inspect
from typing import Type, Set

# 你的业务基类
class Human:
    def foo(self):
        ...

def has_self_method_call(cls: Type, target_method: str = 'foo') -> bool:
    """检测类是否存在 self.{target_method}() 调用(含继承的未重写方法)"""
    # 仅校验Human的子类
    if not issubclass(cls, Human):
        return False
    
    seen_methods: Set[str] = set()
    # 按MRO顺序遍历除Human外的所有父类
    human_idx = cls.__mro__.index(Human)
    for base_cls in cls.__mro__[:human_idx]:
        for method_name, method in inspect.getmembers(base_cls, inspect.isfunction):
            # 已存在同名方法说明子类已重写,跳过父类版本
            if method_name in seen_methods:
                continue
            seen_methods.add(method_name)
            
            # 解析方法源码
            try:
                source_code = inspect.getsource(method)
                ast_tree = ast.parse(source_code)
            except OSError:
                # 无法获取源码的内置/扩展方法直接跳过
                continue
            
            # 查找self.xxx()调用节点
            for node in ast.walk(ast_tree):
                if (
                    isinstance(node, ast.Call)
                    and isinstance(node.func, ast.Attribute)
                    and isinstance(node.func.value, ast.Name)
                    and node.func.value.id == 'self'
                    and node.func.attr == target_method
                ):
                    return True
    return False

# 测试用例校验逻辑
def validate_callsfoo_registry(all_human_subclasses: Set[Type], registry: dict):
    actual_call_classes = set(cls for cls in all_human_subclasses if has_self_method_call(cls))
    registered_classes = set(registry.values())
    
    # 校验漏登
    missing = actual_call_classes - registered_classes
    assert not missing, f"漏登类:{[c.__name__ for c in missing]}"
    # 校验多登
    extra = registered_classes - actual_call_classes
    assert not extra, f"误登类:{[c.__name__ for c in extra]}"

适配说明

该方案自动覆盖你示例中的所有场景:

  • 可以识别Anna类中bar方法的直接调用
  • 会排除仅重写foo但没有调用self.foo的Bob类
  • 可以识别Charlie类中baz方法内分支判断里的调用
  • 可以识别继承了Charlie的baz方法、没有重写的David类

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 23:27:00