2011-08-28 14 views
10

PyYAMLのドキュメントでこれを行う方法を見つけることができませんでした。私はYAMLで定義したPythonクラスを表現したいのですが、YAMLで指定されていない場合はコンストラクタのパラメータに与えられたデフォルト値を持っています。たとえば:pyyamlのデフォルトのコンストラクタパラメータ

>>> 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 "<stdin>", line 4, in <module> 
    File "<stdin>", line 7, in __repr__ 
AttributeError: 'Test' object has no attribute 'bar' 

私はそれがバー= 3でテストオブジェクトを作成すると予想、私はそれがオブジェクトを作成するときに、それは私のコンストラクタをバイパス思います。私はYAMLでバーのマッピングが含まれている場合は、すべてが期待どおりに動作します:

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

誰もが、私はそれがデフォルト値を使用することができます方法を知っていますか?

答えて

9

同じ問題が発生しました。何らかの理由でyaml_tagが機能しません。だから私は別のアプローチを使用:alexanderlukanin13の答えに基づいて

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

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

出力。ここに私のカットです。

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 
:あなたはこのようにそれを使用することができます

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 

関連する問題