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

Python 3.7中如何动态获取并实例化函数内的局部类?

获取Python函数/方法内局部作用域的自定义数据类类型

核心结论

无法直接通过getattr和模块属性链(如Foo.bar.<locals>.TestClass)获取函数内的局部类,原因如下:

  • <locals>不是可访问的对象属性,只是Python为局部作用域内的类生成的名称标识
  • 局部类默认仅存在于函数执行时的局部命名空间中,函数执行结束后若没有外部引用,会被垃圾回收

可行解决方案

方案1:将局部类绑定到外部可访问的命名空间

在函数执行时,把局部类挂载到类属性、模块属性或实例属性上,让它在局部作用域外留存:

from dataclasses import dataclass

class Foo:
    def bar(self) -> None:
        @dataclass
        class TestClass:
            val1: str
            val2: int
        # 绑定到Foo类的属性,外部可直接访问
        Foo.TestClass = TestClass
        instance = TestClass("", 1)
        print(type(instance))

test = Foo()
test.bar()
# 反序列化时直接获取
module = __import__("__main__")
foo_type = getattr(module, "Foo")
test_class_type = getattr(foo_type, "TestClass")
print(test_class_type)  # <class '__main__.Foo.bar.<locals>.TestClass'>

方案2:通过实例属性留存局部类引用

如果需要保留局部类的作用域隔离,可以把它绑定到实例的属性上:

from dataclasses import dataclass

class Foo:
    def bar(self) -> None:
        @dataclass
        class TestClass:
            val1: str
            val2: int
        # 绑定到当前实例的属性
        self.local_test_class = TestClass
        instance = TestClass("", 1)
        print(type(instance))

test = Foo()
test.bar()
# 反序列化时通过实例获取
test_class_type = test.local_test_class
print(test_class_type)

方案3:结合__qualname__和留存的引用查找

如果无法修改原函数代码,但能确保局部类被外部引用留存,可以利用类的__qualname__(包含作用域路径)来遍历查找:

import sys
from dataclasses import dataclass

class Foo:
    def bar(self) -> None:
        @dataclass
        class TestClass:
            val1: str
            val2: int
        # 把局部类存入实例的字典中留存
        self._local_classes = {"TestClass": TestClass}
        instance = TestClass("", 1)
        print(type(instance))

def resolve_local_class(module_name, qualname, instance=None):
    parts = qualname.split('.')
    current = sys.modules[module_name]
    for idx, part in enumerate(parts):
        if part == '<locals>':
            # 从实例的留存字典中获取局部作用域的类
            current = instance._local_classes
            continue
        if idx == len(parts)-1:
            return current.get(part) if isinstance(current, dict) else getattr(current, part)
        current = getattr(current, part)

test = Foo()
test.bar()
# 利用类的__qualname__和实例引用查找
test_class_type = resolve_local_class('__main__', test._local_classes['TestClass'].__qualname__, test)
print(test_class_type)

注意事项

  • 局部类必须被外部引用留存,否则函数执行结束后会被垃圾回收,无法再获取
  • 避免依赖栈帧(如inspect模块的栈帧操作)来获取局部类,这种方式不稳定,易受Python版本或运行环境影响

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 04:08:12