Default constructor parameters in pyyaml

后端 未结 2 583
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-31 08:19

I haven\'t been able to find out how to do this in the PyYAML documentation. I want to represent python classes I\'ve defined in YAML, and have a default value given to a pa

相关标签:
2条回答
  • 2020-12-31 08:30

    Based on alexanderlukanin13's answer. Here's my cut.

    import yaml
    
    YAMLObjectTypeRegistry = {}
    
    def register_type(target):
        if target.__name__ in YAMLObjectTypeRegistry:
            print "{0} already in registry.".format(target.__name__)
        elif 'yaml_tag' not in target.__dict__.keys():
            print target.__dict__
            raise TypeError("{0} must have yaml_tag attribute".format(
                target.__name__))
        elif target.__dict__['yaml_tag'] is None:
            pass
        else:
            YAMLObjectTypeRegistry[target.__name__] = target
            yaml.add_constructor(
                    target.__dict__['yaml_tag'],
                    lambda loader, node: target(**loader.construct_mapping(node)))
            print "{0} added to registry.".format(target.__name__)
    
    class RegisteredYAMLObjectType(type):
        def __new__(meta, name, bases, class_dict):
            cls = type.__new__(meta, name, bases, class_dict)
            register_type(cls)
            return cls
    
    class RegisteredYAMLObject(object):
        __metaclass__=RegisteredYAMLObjectType
        yaml_tag = None
    

    You can then use it like this:

    class MyType(registry.RegisteredYAMLObject):
        yaml_tag = u'!mytype'
        def __init__(self, name, attr1='default1', attr2='default2'):
            super(MyType, self).__init__()
            self.name = name
            self.attr1 = attr1
            self.attr2 = attr2
    
    0 讨论(0)
  • I encountered the same problem: yaml_tag doesn't work for some reason. So I used alternative approach:

    import yaml
    
    def constructor(loader, node) :
        fields = loader.construct_mapping(node)
        return Test(**fields)
    
    yaml.add_constructor('!Test', constructor)
    
    class Test(object) :
        def __init__(self, foo, bar=3) :
            self.foo = foo
            self.bar = bar
        def __repr__(self):
            return "%s(foo=%r, bar=%r)" % (self.__class__.__name__, self.foo, self.bar)
    
    print yaml.load("""
    - !Test { foo: 1 }
    - !Test { foo: 10, bar: 20 }""")
    

    Output:

    [Test(foo=1, bar=3), Test(foo=10, bar=20)]
    
    0 讨论(0)
提交回复
热议问题