2012-05-09 90 views
1

我目前空白的是如何以有效的方式做到這一點。我想過使用對象,但我沒有看到他們在這種情況下如何提供幫助。有任何想法嗎?需要將函數字典轉換爲結果字典的Python技巧

from random import choice 
from copy import deepcopy 


def main(): 

    def rand_int(): 
     return choice(['yes', 'no']) 

    # any nesting, functions possible 
    spec = { 
     'answer': rand_int, 
     'next': {'answer': rand_int}, 
     'the_answer': 42 
    } 

    #### looking for elegant (automatic) way to do this 
    result = deepcopy(spec) 
    result['answer'] = result['answer']() 
    result['next']['answer'] = result['next']['answer']() 
    #### until here 

    # result2 = ... 

    print 'result: %s' % result 


if __name__ == '__main__': 
    main() 

請不要告訴我使用xsd!

回答

8

您可以在dictionary comprehension與一行做到這一點:

{key: function() for key, function in mydictionary.items()} 

當然,當值不是一個函數,這將引發錯誤,因此,如果這是一個可能性,我們可以簡單地添加一個請與the callable() builtin

{key: (function() if callable(function) else function) for key, function in mydictionary.items()} 

然後,我們需要處理你的回答必須是遞歸的事實,這使得它稍微複雜一些,但不要太用力,修復:

def call_all_callables_in_dict(mapping): 
    if hasattr(mapping, "items"): 
     return {key: call_all_callables_in_dict(value) for key, value in mapping.items()} 
    elif callable(mapping): 
     return mapping() 
    else: 
     return mapping 

請注意,如果您的對象具有items屬性或方法,您希望在dict中存儲該函數,則可能會導致問題。我會建議更改該屬性或方法的名稱,或者用isinstance(dict)替換該檢查。

我還想指出,對於誤導函數名稱rand_int,返回字符串'yes''no'可能是一樣糟糕。在這些情況下,您通常還需要True/False

正如在評論中指出的那樣,Python 2.7之前,你可能沒有字典解析。爲了解決這個問題,dict()將採取一個元組的發電機,這樣你就可以替換的字典的理解,像這樣:

{x: y for x, y in something.items()} 

有了:

dict((x, y) for x, y in something.items()) 

因此,在全:

from random import choice 

def rand_int(): 
     return choice(['yes', 'no']) 

spec = { 
    'answer': rand_int, 
    'next': {'answer': rand_int}, 
    'the_answer': 42 
} 

def call_all_callables_in_dict(mapping): 
    if hasattr(mapping, "items"): 
     return {key: call_all_callables_in_dict(value) for key, value in mapping.items()} 
    elif callable(mapping): 
     return mapping() 
    else: 
     return mapping 

print(call_all_callables_in_dict(spec)) 

給我們:

{'answer': 'no', 'the_answer': 42, 'next': {'answer': 'yes'}} 
+0

@TimPietzcker我意識到,當我發佈,更新與兩個答案。 –

+0

期待:) –

+0

請注意,dict解析工作在Python 2.7+。同樣的語法也是用冒號:'{key:鍵的值,dict.items()中的值}' –