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

如何在装饰器中无需预知变量名遍历函数内所有变量

问题根因

初始代码无法检测到函数内部变量,核心问题出在两个认知偏差上:

  • dir(f) 遍历的是函数对象本身挂载的属性,和函数运行时内部作用域创建的局部变量完全无关
  • 装饰器是在函数定义阶段执行的,此时被装饰函数的内部代码还没运行,局部变量根本没有被创建,自然不可能被遍历到。另外直接在装饰器外层调用locals()/globals(),拿到的也只是装饰器作用域、全局作用域的变量,完全触达不到函数执行时的内部栈帧。
可运行实现方案

要实现运行时检测函数内部指定类型变量的需求,可以借助Python的trace追踪机制,在被装饰函数执行到返回节点时,读取当前栈帧的局部变量表做校验,代码如下:

import sys
from types import FrameType
from typing import Callable, Any

def check_float_in_func(func: Callable) -> Callable:
    def _trace_callback(frame: FrameType, event: str, arg: Any):
        # 仅在被装饰函数即将返回时触发检测
        if event == "return" and frame.f_code is func.__code__:
            for val in frame.f_locals.values():
                if isinstance(val, float):
                    print("FLOAT WAS USED!")
                    break
        return _trace_callback

    def wrapper(*args, **kwargs):
        # 注册追踪回调
        sys.settrace(_trace_callback)
        try:
            return func(*args, **kwargs)
        finally:
            # 执行完成后关闭追踪,避免影响其他逻辑
            sys.settrace(None)
    return wrapper

@check_float_in_func
def func2():
    THE_INTEGER_VARIABLE = 10
    THE_FLOAT_VARIABLE = 0.5

func2()

运行上述代码会正常输出FLOAT WAS USED!,符合预期。

补充说明
  • 类型判断建议使用isinstance()代替type(xxx) == 目标类型,可以正确兼容子类场景,判断逻辑更鲁棒
  • 如果需要在变量赋值的第一时间就触发检测,可以调整trace回调的判断逻辑,响应line事件逐行扫描局部变量的变化
  • 如果不想依赖trace机制,也可以通过解析、修改函数的AST抽象语法树,在所有赋值语句后自动插入类型检测逻辑,不过该方案实现复杂度更高,适合复杂的静态扫描+运行时校验场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 17:09:14