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

无法获取带@staticmethod装饰器的调用类方法所属类名

问题:静态方法调用场景下无法获取调用类名的解决思路

之前参考相关方法实现函数内获取调用类名时,遇到了静态方法的特殊问题:stack[1].frame.f_locals["self"].__class__.__name__ 在实例方法调用场景下可以正常获取类名,但在带@staticmethod装饰器的类方法中调用时,会抛出KeyError: 'self'错误。

示例代码如下,实例方法调用some_func可正常运行,但静态方法调用会报错:

def some_func():
    '... some_code ...'
    import inspect
    stack = [x for x in inspect.stack() if 'My_Module' in str(x)]
    try:
        src = '<{}>.'.format(stack[1].frame.f_locals["self"].__class__.__name__)
    except:
        from traceback import format_exc
        print(format_exc())
        src = ''
    '... some_code ...'

class SomeClass:
    @staticmethod
    def tester():
        some_func()

请问有什么解决思路?


解决思路

1. 区分调用场景,兼容静态方法与实例方法

静态方法本身没有self参数,所以不能直接从f_locals中取self。可以通过检查调用栈的代码上下文,结合函数的__qualname__来获取类名——Python中函数的__qualname__会包含完整的类层级路径,格式为类名.方法名。

修改后的some_func示例:

def some_func():
    '... some_code ...'
    import inspect
    src = ''
    # 获取调用栈,跳过当前函数本身
    stack = inspect.stack()
    if len(stack) >= 2:
        caller_frame = stack[1].frame
        caller_code = caller_frame.f_code
        # 实例方法场景:从f_locals取self获取类名
        if 'self' in caller_frame.f_locals:
            cls_name = caller_frame.f_locals['self'].__class__.__name__
            src = f'<{cls_name}>'
        else:
            # 静态方法场景:解析__qualname__获取类名
            qualname = caller_code.co_qualname
            if '.' in qualname:
                cls_name = qualname.split('.')[0]
                src = f'<{cls_name}>'
    '... some_code ...'

2. 结合模块验证提升可靠性

如果担心__qualname__解析出错(比如嵌套类、复杂方法命名),可以结合inspect.getmodule从调用模块中验证类是否存在:

def some_func():
    '... some_code ...'
    import inspect
    src = ''
    stack = inspect.stack()
    if len(stack) >= 2:
        caller_frame = stack[1].frame
        caller_code = caller_frame.f_code
        caller_module = inspect.getmodule(caller_frame)
        
        if 'self' in caller_frame.f_locals:
            cls_name = caller_frame.f_locals['self'].__class__.__name__
            src = f'<{cls_name}>'
        else:
            qualname_parts = caller_code.co_qualname.split('.')
            if len(qualname_parts) >= 2:
                cls_name = qualname_parts[0]
                # 验证模块中是否存在该类,避免解析错误
                if hasattr(caller_module, cls_name):
                    src = f'<{cls_name}>'
    '... some_code ...'

3. 显式传递类名的替代方案

如果依赖调用栈的实现存在兼容性风险(比如Python版本差异、多层装饰器干扰),最直接的方式是调用时显式传递类名:

def some_func(caller_cls_name=''):
    '... some_code ...'
    src = f'<{caller_cls_name}>' if caller_cls_name else ''
    '... some_code ...'

class SomeClass:
    @staticmethod
    def tester():
        some_func(caller_cls_name=SomeClass.__name__)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 05:33:58