python - 我的标签是否过载,或者这是将构造函数添加到 yaml 配置或其他内容的范围问题

标签 python yaml pyyaml

写了一个辅助函数来包装简单的对象构造函数并使它们可以作为标签访问,但我要么有一个错误,要么编写构造函数是因为闭包导致了冲突

import yaml
from yaml.constructor import ConstructorError


def add_init_constuctors(*klasses, loader=yaml.SafeLoader):
    for klass in klasses:
        name = klass.__name__

        def constructor(loader, node):
            try:
                fields = loader.construct_mapping(node)
            except ConstructorError:
                fields = {}

            return klass(**fields)

        yaml.add_constructor(
            f"!{name}",
            constructor,
            Loader=loader,
        )
        print(f"added !{name}")
        print(yaml.load(f"!{name}", Loader=loader))

    print(
        [
            (klass.__name__, yaml.load(f"!{klass.__name__}", Loader=loader))
            for klass in klasses
        ]
    )

class A(dict):
    def __repr__(self):
        return "A()"

class B(dict):
    def __repr__(self):
        return "B()"

if __name__ == "__main__":
    add_init_constuctors(A, B)

运行这段代码输出

added !A
A()
added !B
B()
[('A', B()), ('B', B())]

如您所见,当添加 A 时它会正确加载,但是一旦添加了 B 标签,就会尝试访问 A返回 B 构造函数

我希望,即使它们包含在范围内,闭包中定义的函数也会保留在构造函数标签中并且是正确的/可访问的。

最佳答案

发生这种情况是因为您的内部函数在 klass 变量上有一个闭包,即每当 constructor 执行时,它会查找 current 的值klass,不是添加构造函数时的那个。

解决此问题的最简单方法是在函数中生成构造函数(我删除了 sklearn 内容,因为它与问题无关):

import yaml
from yaml.constructor import ConstructorError

class A(dict):
    def __repr__(self):
        return "A()"

class B(dict):
    def __repr__(self):
        return "B()"

def gen_constructor(klass):
    def ret(loader, node):
        try:
            fields = loader.construct_mapping(node)
        except ConstructorError:
            fields = {}
        return klass(**fields)
    return ret

def add_init_constuctors(*klasses, loader=yaml.SafeLoader):
    for klass in klasses:
        name = klass.__name__

        yaml.add_constructor(
            f"!{name}",
            gen_constructor(klass),
            Loader=loader,
        )
        print(f"added !{name}")
        print(yaml.load(f"!{name}", Loader=loader))

    print(
        [
            (klass.__name__, yaml.load(f"!{klass.__name__}", Loader=loader))
            for klass in klasses
        ]
    )


if __name__ == "__main__":
    add_init_constuctors(A, B)

现在,res 捕获函数gen_constructor 的参数klass,而不是klass 中的变量添加初始化构造函数。因此,输出是:

added !A
A()
added !B
B()
[('A', A()), ('B', B())]

关于python - 我的标签是否过载,或者这是将构造函数添加到 yaml 配置或其他内容的范围问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74910887/

相关文章:

python - 有没有办法使用 Jinja2/Ansible 设置整数的默认最小值?

python - string.format() 在我的脚本中停止正常工作

YAML 在文件中附加数据

python - 在 Keras 中进行文本分类时出错

python - 为什么 pip 即使拥有用户和系统存储库的权限也无法安装包?

使用 transchoice 进行 symfony2 翻译

Perl:YAML 在数组中迭代?

python - 使用 yamltodb 将 YAML 数据转换为数据框

python - 在 YAML 中执行算术运算?

python:PyYAML 模块未解析为对象