You need to enable JavaScript to run this app. PyYAML自定义构造类__init__方法无法访问嵌套实例属性问题
优惠活动
大模型
产品
解决方案
定价
更多

PyYAML自定义构造类__init__方法无法访问嵌套实例属性问题

问题原因及修复方案

核心结论

你遇到的情况既不是配置遗漏也不是PyYAML的功能限制,是对PyYAML的嵌套节点解析逻辑和自定义构造器的使用方法有误导致的。

具体问题原因

  • __init__中嵌套参数为空、实例化后属性正常:PyYAML默认采用延迟解析策略处理嵌套节点,调用loader.construct_mapping()时如果没有传入deep=True参数,方法返回的字典中嵌套结构会先填充空容器占位,等顶层节点构造完成后再递归解析回填内容。你在__init__执行阶段拿到的就是还未填充的空容器,整个加载流程结束后嵌套值回填完成,所以__repr__可以读到正确值。
  • __repr__返回类名变为YAML键名:这个属于自定义逻辑错误,大概率是你在构造器中错误地把YAML节点的tag、或者解析出来的映射键值赋值给了实例的__class__.__name__属性,或者没有显式调用PrintAttributes的构造方法,误用了PyYAML内部通用对象构造逻辑导致类名被覆盖。

修复方案

正确的自定义构造器写法

import yaml

# 你的自定义类
class PrintAttributes:
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __repr__(self):
        # 显式写死类名,避免动态变量污染
        return f"PrintAttributes(a={self.a}, b={self.b})"

# 自定义构造器
def print_attr_constructor(loader, node):
    # 关键参数deep=True强制立即递归解析所有嵌套节点
    params = loader.construct_mapping(node, deep=True)
    # 显式实例化,不要用动态赋值逻辑
    return PrintAttributes(**params)

# 注册构造器
yaml.add_constructor('!PrintAttributes', print_attr_constructor, Loader=yaml.FullLoader)

测试验证

nested_yaml = """
!PrintAttributes
a: test
b:
  key1: 嵌套值1
  key2: 嵌套值2
"""

res = yaml.load(nested_yaml, Loader=yaml.FullLoader)
print(res)
# 正常输出:PrintAttributes(a=test, b={'key1': '嵌套值1', 'key2': '嵌套值2'})

异常排查

如果调整后仍然出现类名异常,检查两处逻辑:

  • PrintAttributes的__repr__方法有没有错误引用外部动态变量
  • 构造器中有没有出现修改实例__class__、__name__属性的逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 19:06:03