Python函数参数中如何获取字典名及关联键而非取值?
解决Python函数中提取字典及键路径而非值的问题
Python采用求值传递机制,当你调用abc(thisdict["brand"]["color"], ...)时,thisdict["brand"]["color"]会先被计算为实际值(比如示例中的"Red")再传入函数,所以直接从args中无法获取原始的字典和键路径。以下是几种可行的解决方法:
方案1:显式传递字典与键路径(推荐,简单可靠)
直接调整调用方式,将字典对象和层级键列表分开传入,函数可直接获取所需信息,同时也能自行计算对应的值。
def abc(dict_obj, key_path, *args): # 反向查找字典名称(全局变量场景,局部变量用locals()替代globals()) dict_name = next(k for k, v in globals().items() if v is dict_obj) print(f"字典名称: {dict_name}") print(f"键路径: {key_path}") # 可选:获取对应的值 current_value = dict_obj for key in key_path: current_value = current_value[key] print(f"对应的值: {current_value}") # 处理其他参数 print(f"其他参数: {args}") # 测试 thisdict = {"brand": {"color":"Red","model": "Mustang"},"manufactured": {"year":"1964","month":"Oct"}} abc(thisdict, ["brand", "color"], "111", "222")
输出:
字典名称: thisdict 键路径: ['brand', 'color'] 对应的值: Red 其他参数: ('111', '222')
方案2:传递表达式字符串并解析(适合需贴近原调用形式的场景)
传递字典访问的表达式字符串,通过正则或AST解析提取信息。注意:使用eval存在安全风险,仅在完全可控的输入场景下使用。
方法A:正则表达式解析
import re def abc(expr_str, *args): match = re.match(r"(\w+)(\['[\w]+'\])+", expr_str) if match: dict_name = match.group(1) keys = re.findall(r"\['([\w]+)'\]", expr_str) print(f"字典名称: {dict_name}") print(f"键路径: {keys}") # 获取对应的值 dict_obj = globals()[dict_name] current_value = dict_obj for key in keys: current_value = current_value[key] print(f"对应的值: {current_value}") print(f"其他参数: {args}") # 测试 abc("thisdict['brand']['color']", "111", "222")
方法B:AST解析(更可靠)
用Python内置的ast模块解析表达式,能准确处理复杂键路径:
import ast def abc(expr_str, *args): tree = ast.parse(expr_str, mode='eval').body current_node = tree keys = [] # 遍历AST节点提取键路径 while isinstance(current_node, ast.Subscript): keys.append(current_node.slice.value.s) current_node = current_node.value dict_name = current_node.id print(f"字典名称: {dict_name}") print(f"键路径: {keys[::-1]}") # 反转得到正确的层级顺序 # 获取对应的值 dict_obj = globals()[dict_name] current_value = dict_obj for key in keys[::-1]: current_value = current_value[key] print(f"对应的值: {current_value}") print(f"其他参数: {args}") # 测试 abc("thisdict['brand']['color']", "111", "222")
方案3:解析调用栈源代码(不推荐,依赖环境)
通过inspect模块获取调用时的源代码,解析参数表达式。该方法依赖源代码可读性,打包或交互式环境中可能失效,仅作参考:
import inspect import ast import re def abc(*args): frame = inspect.currentframe().f_back source = inspect.getsource(frame).strip() match = re.search(r"abc\((.*?)\)", source) if match: args_expr = match.group(1).split(',')[0].strip() tree = ast.parse(args_expr, mode='eval').body current_node = tree keys = [] while isinstance(current_node, ast.Subscript): keys.append(current_node.slice.value.s) current_node = current_node.value dict_name = current_node.id print(f"字典名称: {dict_name}") print(f"键路径: {keys[::-1]}") print(f"参数值: {args}") # 测试 thisdict = {"brand": {"color":"Red","model": "Mustang"},"manufactured": {"year":"1964","month":"Oct"}} abc(thisdict["brand"]["color"], "111", "222")
核心总结
Python的求值机制决定了直接传入表达式无法保留原始字典和键路径信息,必须通过修改传参方式或解析表达式/源代码来实现。优先选择方案1,它简洁、安全且可读性强,无额外依赖或风险。
内容的提问来源于stack exchange,提问作者Devarshi Chatterjee
相关产品推荐
相关产品推荐

