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

如何修改deep_get函数以支持嵌套字典中的列表索引访问

让deep_get函数支持嵌套字典与列表索引访问

原函数的局限

原定义的deep_get函数仅能处理纯嵌套字典的取值,当路径中包含列表索引(如person.names[0])时无法正确解析,会返回None。

原函数代码:

from functools import reduce

def deep_get(dictionary, keys, default=None):
    return reduce(
        lambda d, key: d.get(key, default) if isinstance(d, dict) else default,
        keys.split("."),
        dictionary,
    )

测试示例及问题:

person1 = {'person': {'name': {'first': 'John'}}}
print(deep_get(person1, "person.name.first"))   # 输出 John

person2 = {'person': {'names': ['Adam', 'John']}}
print(deep_get(person2, "person.names"))        # 输出 ['Adam', 'John']
print(deep_get(person2, "person.names[0]"))     # 输出 None(不符合预期,期望返回Adam)

修改方案

要支持列表索引,需要先解析路径中的索引部分,将类似names[0]的节点拆分为键名names和索引0,然后分别处理字典取值和列表索引访问。

修改后的函数代码:

from functools import reduce
import re

def deep_get(dictionary, keys, default=None):
    # 正则匹配路径节点,提取键名和可选的数字索引
    key_parser = re.compile(r'(\w+)(?:\[(\d+)\])?')

    def traverse(current, key_segment):
        match = key_parser.fullmatch(key_segment)
        if not match:
            return default
        
        key, idx_str = match.groups()
        # 先处理字典键取值
        if isinstance(current, dict):
            current = current.get(key, default)
            # 如果当前值是列表且存在索引,尝试访问索引
            if idx_str is not None and isinstance(current, list):
                try:
                    current = current[int(idx_str)]
                except (IndexError, ValueError):
                    return default
        # 处理当前为列表且节点是纯索引的情况(如路径为"list[1]")
        elif idx_str is not None and isinstance(current, list):
            try:
                current = current[int(idx_str)]
            except (IndexError, ValueError):
                return default
        else:
            # 非字典/可索引列表,返回默认值
            return default
        
        return current if current is not default else default

    # 按点分割路径后逐个处理节点
    return reduce(traverse, keys.split("."), dictionary)

测试验证

运行以下代码验证效果:

person1 = {'person': {'name': {'first': 'John'}}}
print(deep_get(person1, "person.name.first"))   # 输出 John

person2 = {'person': {'names': ['Adam', 'John']}}
print(deep_get(person2, "person.names"))        # 输出 ['Adam', 'John']
print(deep_get(person2, "person.names[0]"))     # 输出 Adam
print(deep_get(person2, "person.names[1]"))     # 输出 John
print(deep_get(person2, "person.names[2]"))     # 输出 None(索引越界,返回默认值)

关键改进点

  • 用正则表达式拆分路径节点,识别字典键和列表索引的组合格式
  • 对列表索引访问添加异常捕获,处理索引越界、非数字索引等异常情况,返回预设默认值
  • 兼容原有的纯字典路径取值逻辑,不破坏原有功能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:33:17