2011-08-28 18 views
10

Bunu PyYAML belgelerinde nasıl yapamayacağımı anlayamadım. YAML'de tanımladığım python sınıflarını temsil etmek ve YAML'de belirtilmemişse yapıcıdaki bir parametreye verilen varsayılan bir değere sahip olmak istiyorum. Örneğin:Varsayılan kurucu parametreleri pyyaml ​​içinde

>>> 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' 

Ben barda = 3 olan bir test nesnesi oluşturmak bekleniyordu, ama nesne oluşturduğunda bu benim yapıcı atlar sanırım. Ben YAML barda bir eşleme dahil, her şey beklendiği gibi çalışır:

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

kimse bunu varsayılan değeri kullanmak olabilir biliyor mu?

cevap

9

Aynı sorunla karşılaştım: yaml_tag bir nedenden dolayı çalışmıyor.

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

Çıktı: Ben alternatif bir yaklaşım kullanılmaktadır

alexanderlukanin13 cevabı dayanarak
[Test(foo=1, bar=3), Test(foo=10, bar=20)] 
0

. İşte benim işim.

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 

Daha sonra, bu gibi kullanabilirsiniz:

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