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

如何获取类实例字段?编写get_members函数输入类本身获成员

类与实例成员识别及get_members函数实现

一、给定类名,如何发现实例级字段?

实例级字段(比如Mock里的a)是在类实例化时通过self.xxx = ...绑定到实例的,类本身并不存储这些字段,所以直接用vars(clz)、dir(clz)或inspect模块查询类时,无法直接获取到这类字段。要识别它们,有两种实用思路:

  • 动态实例化提取:创建类的临时实例(处理__init__参数时,用占位值如None填充),再通过实例的__dict__或vars()提取字段名。这种方法简单直接,适合大多数场景。
  • 解析__init__源码:用ast模块解析__init__函数的代码,找出所有对self赋值的语句,提取对应的字段名。这种方法不需要实例化类,适合无法创建实例的场景(比如__init__依赖外部资源)。

二、实现get_members函数

针对给定的Mock类,要实现输入类本身时返回a和b,下面提供两种可行实现:

方法1:动态实例化提取(简单直接)

import inspect

class Mock:
    def __init__(self, a):
        self.a = a

    def b(self):  # 修正原代码中b方法缺少self参数的问题
        pass

def get_members(clz):
    """return all the members of clz and its instance, including static methods, 
       class methods, instance level methods and fields
       e.g., given Mock, return a and b
    """
    # 收集类层面的成员(过滤内置特殊成员)
    class_members = set()
    for name, _ in inspect.getmembers(clz):
        if not name.startswith('__'):
            class_members.add(name)
    
    # 动态创建实例,提取实例字段
    instance_members = set()
    try:
        # 自动生成__init__所需的占位参数
        sig = inspect.signature(clz.__init__)
        args = [None] * (len(sig.parameters) - 1)
        instance = clz(*args)
        instance_members = set(instance.__dict__.keys())
    except Exception:
        # 实例化失败时跳过实例字段收集
        pass
    
    # 合并并返回排序后的结果
    return sorted(class_members.union(instance_members))

# 测试
print(get_members(Mock))  # 输出: ['a', 'b']

方法2:解析__init__源码(无需实例化)

import ast
import inspect

class Mock:
    def __init__(self, a):
        self.a = a

    def b(self):
        pass

def get_instance_fields_from_init(clz):
    """从__init__方法中解析实例字段"""
    fields = set()
    if not hasattr(clz, '__init__'):
        return fields
    
    # 获取并解析__init__的源码
    source_code = inspect.getsource(clz.__init__)
    tree = ast.parse(source_code)
    
    # 遍历语法树,找出self.xxx的赋值语句
    for node in ast.walk(tree):
        if isinstance(node, ast.Assign):
            for target in node.targets:
                if (isinstance(target, ast.Attribute) 
                    and isinstance(target.value, ast.Name) 
                    and target.value.id == 'self'):
                    fields.add(target.attr)
    return fields

def get_members(clz):
    """return all the members of clz and its instance, including static methods, 
       class methods, instance level methods and fields
       e.g., given Mock, return a and b
    """
    # 收集类层面的成员
    class_members = set()
    for name, _ in inspect.getmembers(clz):
        if not name.startswith('__'):
            class_members.add(name)
    
    # 解析__init__获取实例字段
    instance_fields = get_instance_fields_from_init(clz)
    
    # 合并并返回排序后的结果
    return sorted(class_members.union(instance_fields))

# 测试
print(get_members(Mock))  # 输出: ['a', 'b']

注意事项

  • 原Mock类中的b()方法缺少self参数,不符合Python实例方法的定义,会导致调用实例的b()时出错,上述代码已修正该问题。
  • 方法1中如果__init__需要的参数无法用占位值填充(比如必须是特定类型),可根据实际场景调整参数传递逻辑。
  • 方法2只能识别__init__中直接对self赋值的字段,无法识别其他实例方法中动态添加的字段,这类场景仍需结合实例化方式处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 16:43:21