【问题标题】:YAML does not call the constructorYAML 不调用构造函数
【发布时间】:2012-10-31 03:20:40
【问题描述】:

我已经尝试按照here 的说明进行操作,这导致我找到了这个代码:

import yaml
class Step(yaml.YAMLObject):

    yaml_tag = "!step"

    def __init__(self, *args, **kwargs):
        raise Exception("Intentionally.")

yaml.load("""
--- !step
    foo: bar
    ham: 42
""")

预期行为:出现异常。但我观察到的是,我的 YAML 标记会生成一个 Step 实例,我可以使用它、访问方法、属性(如上面代码中的 foo)等等。阅读文档,我找不到我的错误,因为它建议使用所有键值对作为关键字参数调用构造函数。

基本上文档中的示例有效,但不是因为构造函数的实现,而是因为键值对(Monster 的属性)用于填充对象的字典。

这里有人知道吗?

我正在使用 python3,但在 python2 中进行了快速评估并观察到了相同的结果。

编辑

我想要做的:留在链接示例(文档)中,如果 Monsters nameB 开头,则将 ac 的值加倍。

【问题讨论】:

    标签: python python-3.x yaml


    【解决方案1】:

    来自文档:

    yaml.YAMLObject 使用元类魔法来注册一个构造函数,它将 YAML 节点转换为一个类实例,以及一个表示器,它将一个类实例序列化为一个 YAML 节点。

    在内部,由yaml.YAMLObject 注册的默认constructor 将调用YourClass.__new__,然后使用instance.__dict__ 在您的类上设置字段。详情请参阅this method

    根据您想要做什么,您可以在Step.__new__ 中添加一些逻辑(但您不会在**kwargsregister a custom constructor 中获得任何字段。

    【讨论】:

    • 那么文档中的示例可能已经过时了?因为他们显示的构造函数可能不是必需的:它没有被调用并且在那里做了什么,基本上将所有 kwargs 添加为属性,无论如何都完成了。
    【解决方案2】:

    我认为我有一个根本的误解。我不知道这个假设是否成立,但我认为

    load, dump = yaml.load, yaml.dump
    foo = "any valid yaml string"
    
    load(foo) == load(dump(load(foo))) # should be true
    

    如果我现在按照问题中的建议进行操作,在加载时真正更改属性,会更改此“方程式”并导致我很可能不想要的行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-28
      • 2018-02-28
      • 2019-02-01
      • 2022-12-03
      • 2015-02-21
      • 1970-01-01
      相关资源
      最近更新 更多