Parámetros de constructor por defecto en pyyaml

No he podido averiguar cómo hacerlo en la documentación de PyYAML. Quiero representar las clases de python que he definido en YAML, y tengo un valor predeterminado dado a un parámetro en el constructor si no está especificado en el YAML. Por ejemplo:

>>> class Test(yaml.YAMLObject): ... yaml_tag = u"!Test" ... 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) ... >>> yaml.load(""" ... --- !Test ... foo: 5 ... """) Traceback (most recent call last): File "", line 4, in  File "", line 7, in __repr__ AttributeError: 'Test' object has no attribute 'bar' 

Esperaba que creara un objeto de prueba con bar = 3, pero supongo que omite a mi constructor cuando crea el objeto. Si incluyo un mapeo para barra en el YAML, todo funciona como se espera:

 >>> yaml.load(""" ... --- !Test ... foo: 5 ... bar: 42 ... """) Test(foo=5, bar=42) 

¿Alguien sabe cómo puedo hacer que use un valor predeterminado?

Encontré el mismo problema: yaml_tag no funciona por alguna razón. Así que utilicé un enfoque alternativo:

 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 }""") 

Salida:

 [Test(foo=1, bar=3), Test(foo=10, bar=20)] 

Basado en la respuesta de alexanderlukanin13. Aquí está mi corte.

 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 

Puedes usarlo así:

 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