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

mar*_*ark 1 python dictionary

我目前对如何以有效的方式做到这一点空白.我想过使用对象,但我不知道在这种情况下他们如何能够提供帮助.有任何想法吗?

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()
Run Code Online (Sandbox Code Playgroud)

请不要告诉我使用xsd!

Gar*_*tty 8

您可以在字典理解中使用一行来完成此操作:

{key: function() for key, function in mydictionary.items()}
Run Code Online (Sandbox Code Playgroud)

当然,当值不是一个函数,因此,如果这是一个可能性,我们可以简单地添加的支票一张,这将引发错误callable()内置:

{key: (function() if callable(function) else function) for key, function in mydictionary.items()}
Run Code Online (Sandbox Code Playgroud)

然后我们需要处理这样一个事实:你的答案需要递归,这使它更复杂,但不难修复:

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
Run Code Online (Sandbox Code Playgroud)

请注意,如果您items希望存储在dict此函数中的具有属性或方法的对象将运行,则可能会导致问题.我建议更改该属性或方法的名称,或替换支票isinstance(dict).

我还要注意,对于误导性的函数名称rand_int,它返回一个'yes'或者'no'可能与它一样糟糕的字符串.一般来说,您也希望True/ False在这些情况下.

正如评论中所述,在Python之前的2.7版本中,您可能没有字典理解.要解决这个问题,dict()需要使用元组生成器,这样就可以替换像这样的字典理解:

{x: y for x, y in something.items()}
Run Code Online (Sandbox Code Playgroud)

附:

dict((x, y) for x, y in something.items())
Run Code Online (Sandbox Code Playgroud)

所以,完整的:

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))
Run Code Online (Sandbox Code Playgroud)

给我们:

{'answer': 'no', 'the_answer': 42, 'next': {'answer': 'yes'}}
Run Code Online (Sandbox Code Playgroud)