Skip to main content
 首页 » 编程设计

将函数字典转换为结果字典所需的python技巧

2025年05月04日11tintown

我目前对如何以有效的方式做到这一点一无所知。我考虑过使用对象,但我看不出它们在这种情况下有什么帮助。有什么想法吗?

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!

请您参考如下方法:

你可以用 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) 替换检查。

我还想指出,对于返回 'yes' 或 'no' 字符串的误导性函数名称 rand_int 可能是尽可能糟糕。通常,在这些情况下您也需要 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'}}