如何在YAML中使用自定义对象作为字典键?
问题与解决方案:用YAML配置以自定义类实例为键的字典
问题背景
定义如下Python类:
class A: def __init__(self, a=None, b=None): self.a = a self.b = b
需要创建一个以该类实例为键的字典,示例代码如下:
m = { A(a=1): 2, A(a=3, b=4): 5, A(b=6): 7 }
尝试用YAML配置时,以下写法出现duplicated mapping key错误:
{ a: 1 } : 2 { a: 3, b: 4 } : 5 { b: 6 } : 7
已知可以用列表形式编写,但希望保留命名字段,同时想了解其他可选的配置格式。
YAML的正确实现方式
YAML解析器会将未包裹的映射结构({a:1})视为普通映射,直接作为键时容易触发语法歧义,导致重复键错误。可以通过两种方式解决:
1. 给映射键添加引号
将映射结构字符串化,用引号包裹作为键:
"{ a: 1 }": 2 "{ a: 3, b: 4 }": 5 "{ b: 6 }": 7
注意:读取后得到的键是字符串类型,需要在Python中额外处理,比如用ast.literal_eval解析字符串为字典,再通过A(**dict_data)转换为类实例。
2. 使用YAML的块式映射键语法
YAML支持用?标记键的起始,后续用块式结构定义键内容:
? a: 1 : 2 ? a: 3 b: 4 : 5 ? b: 6 : 7
这种写法符合YAML规范,不会出现语法错误。读取时,每个?后的块会被解析为Python字典,直接通过A(**key_dict)即可转换为A类的实例。
其他可选配置格式
如果YAML的处理方式不够顺手,还可以考虑以下格式:
JSON:JSON的键只能是字符串,但可以将类实例的参数结构序列化为JSON字符串作为键:
{ "{\"a\": 1}": 2, "{\"a\": 3, \"b\": 4}": 5, "{\"b\": 6}": 7 }读取后用
json.loads解析键字符串为字典,再转换为A实例。TOML:TOML同样只支持字符串键,可将参数结构写成字符串形式:
"{a = 1}" = 2 "{a = 3, b = 4}" = 5 "{b = 6}" = 7读取后需要自定义解析逻辑,将字符串转换为
A类实例。自定义文本格式:如果需求简单,可以自己定义格式,比如每行采用
参数列表:值的形式:a=1:2 a=3,b=4:5 b=6:7自己编写解析函数,分割每行的键值部分,将参数转换为
A实例。
内容的提问来源于stack exchange,提问作者Daniil Lantukhov
相关产品推荐
相关产品推荐

