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

如何使用点表示法字符串读取Python列表/字典对象的值?

问题:通过点表示法字符串获取嵌套字典/列表中的值

给定以下Python对象(列表嵌套字典):

d = [
   {
      'props': {
         'columns': [
            {
               'field': 'Hello'
            }
         ]
      }
   }
]

我希望能用点表示法格式的字符串来获取field的值,比如实现一个类似这样的函数:

get(d, "[0].props.columns[0].field")
>>> 'Hello'

我试过把字典转为Python对象来支持点表示法访问,但不知道怎么通过字符串形式的路径来实现取值。目前的代码能支持d[0].props.columns[0].field这种直接访问,但没法解析字符串形式的路径。另外,当前的Dict2Object类初始化不支持直接传入列表,这部分也需要修复。

以下是我当前的代码实现:

import json

class Dict2Object:
    """
    @DynamicAttrs
    将字典转换为Python对象的类
    """

    def __init__(self, in_dict):
        # 类型检查
        assert isinstance(in_dict, (dict, list))
        # 如果是字典,遍历键值对
        if isinstance(in_dict, dict):
            for key, val in in_dict.items():
                # 处理键名:替换连字符、空格为下划线,转为小写
                key = translate_string(key)
                # 如果值是序列类型(列表、元组、集合)
                if isinstance(val, (list, tuple, set)):
                    # 序列中的字典转为Dict2Object,其他保持原样
                    setattr(
                        self,
                        key,
                        [Dict2Object(x) if isinstance(x, dict) else x for x in val],
                    )
                else:
                    # 非序列值:字典转Dict2Object,其他直接赋值
                    setattr(self, key, Dict2Object(val) if isinstance(val, dict) else val)
    def __repr__(self):
        return "{%s}" % str(
            ", ".join("'%s': %s" % (k, repr(v)) for (k, v) in self.__dict__.items())
        )


def translate_string(string):
    string = string.replace("-", "_")
    string = string.replace(" ", "_")
    string = string.lower()
    return string

d = [
   {
      'props': {
         'columns': [
            {
               'field': 'Hello'
            }
         ]
      }
   }
]

d_obj = Dict2Object(d[0])
print(d_obj.props.columns[0].field)  # 输出: 'Hello'

解决方案

方法1:解析路径字符串直接访问原对象

不需要转换对象,直接解析路径字符串中的索引和属性/键,逐层访问:

def get(obj, path):
    import re
    # 拆分路径节点,处理[0]和.的组合情况
    nodes = re.split(r'(?<=\])\.|\.(?=\[)|(?<=\w)\.(?=\w)', path)
    current = obj
    for node in nodes:
        if node.startswith('[') and node.endswith(']'):
            # 处理列表索引
            idx = int(node[1:-1])
            current = current[idx]
        else:
            # 处理字典键或对象属性
            if isinstance(current, dict):
                current = current[node]
            else:
                current = getattr(current, node)
    return current

# 测试
print(get(d, "[0].props.columns[0].field"))  # 输出: Hello

方法2:改进Dict2Object支持列表,并实现路径解析

先修改Dict2Object让它能处理初始列表,再实现路径解析函数:

class Dict2Object:
    """
    @DynamicAttrs
    将字典或列表转换为Python对象的类
    """
    def __init__(self, data):
        assert isinstance(data, (dict, list))
        if isinstance(data, list):
            # 列表类型转为包含Dict2Object的列表
            self._list = [Dict2Object(item) if isinstance(item, dict) else item for item in data]
        elif isinstance(data, dict):
            for key, val in data.items():
                key = translate_string(key)
                if isinstance(val, (list, tuple, set)):
                    setattr(self, key, [Dict2Object(x) if isinstance(x, dict) else x for x in val])
                else:
                    setattr(self, key, Dict2Object(val) if isinstance(val, dict) else val)
    
    def __getitem__(self, idx):
        # 支持列表索引访问
        if hasattr(self, '_list'):
            return self._list[idx]
        raise TypeError("Not a list-like object")
    
    def __repr__(self):
        if hasattr(self, '_list'):
            return repr(self._list)
        return "{%s}" % str(
            ", ".join("'%s': %s" % (k, repr(v)) for (k, v) in self.__dict__.items())
        )

def translate_string(string):
    string = string.replace("-", "_")
    string = string.replace(" ", "_")
    string = string.lower()
    return string

def get_obj_value(obj, path):
    import re
    nodes = re.split(r'(?<=\])\.|\.(?=\[)|(?<=\w)\.(?=\w)', path)
    current = obj
    for node in nodes:
        if node.startswith('[') and node.endswith(']'):
            idx = int(node[1:-1])
            current = current[idx]
        else:
            current = getattr(current, node)
    return current

# 测试
d_obj = Dict2Object(d)
print(get_obj_value(d_obj, "[0].props.columns[0].field"))  # 输出: Hello

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:13:17