2012-10-02 35 views
1

對象的屬性,我可以使用YAML轉儲蟒蛇對象的層次,所以:選擇性轉儲PyYAML

import yaml 

class C(): 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

class D(): 
    def __init__(self, c, d): 
     self.c = c 
     self.d = d 

d = D(c=C(x=1, y='hi'), 
     d='bye') 

print yaml.dump(d) 

產生輸出:

!!python/object:__main__.D 
c: !!python/object:__main__.C {x: 1, y: hi} 
d: bye 

但我要選擇的隱藏某些屬性。因此,假設我有一個函數attribs_to_dump(obj)這對於任何對象返回屬性名我要轉儲的列表,例如:

def attribs_to_dump(obj): 
    if obj.__class__ == C: return ['x'] 
    if obj.__class__ == D: return ['c'] 

我的問題是,我怎麼勾attribs_to_dumpyaml.dump,讓我得到以下輸出?

!!python/object:__main__.D 
c: !!python/object:__main__.C {x: 1} 

有一個複雜的因素:我想掛接到YAML達到的效果,因爲它爬到對象層次,而不是通過預處理對象層次嘍。其原因是,沒有層次結構中的所有對象都容易服從內省由於setattr/getattr/__dict__魔法存在於我使用的一些庫: - (...

所有幫助非常感謝

回答

1

這是一個!有趣的問題,我很喜歡解決它,謝謝:)

from copy import deepcopy 


class C(object): 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

class D(object): 
    def __init__(self, c, d): 
     self.c = c 
     self.d = d 

d = D(
    c=C(x=1, y='hi'), 
    d='bye' 
) 


FILTER_PARAMS = (
    #(class_reference, process_recursively, ['attributes', 'on', 'whitelist']) 
    (D, True, ['c']), 
    (C, False, ['x']), 
) 

def attr_filter(obj, filter_params): 
    for attr in dir(obj): 
     if attr.startswith('__'): 
      # ignore builtins 
      continue 

     attr_val = obj.__getattribute__(attr) 
     # loop through filter params 
     for (cls, do_recursive, whitelist) in filter_params: 
      if isinstance(obj, cls) and attr in whitelist: 
       # filter class matches the current obj's class and 
       # current attribute is on the whitelist 
       if do_recursive: 
        # must process this attribute the same way as the parent 
        setattr(obj, attr, attr_filter(attr_val, filter_params))     
       # break will avoid the execution of the else clause meaning 
       # the attribute was on the white list so don't delete it 
       break 
     else: 
      # delete the current attribute of the instance as it was 
      # not on the whitelist 
      delattr(obj, attr) 

    return obj 


# do a deepcopy of the object you pass in, so the original will be preserved 
filtered_instance = attr_filter(deepcopy(d), FILTER_PARAMS) 
print dir(filtered_instance) 
print dir(filtered_instance.c) 

# now pass filtered_instance to yaml's dump function 
+0

您確實提供了一個回答我的問題,但在我的情況deepcopy的將無法工作,因爲我連載的對象是很神奇的 - 元類魔法和非常深奧的getattr/setattr覆蓋。我需要在問題中爲遊戲添加更多規則。 – SimonD