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

将函数字典转换为结果字典所需的python技巧,python,dictionary,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': r

我目前对如何有效地做到这一点一无所知。我曾考虑过使用对象,但我不认为它们在这种情况下有什么帮助。有什么想法吗

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

您可以在一个

当然,当值不是函数时,这会引发错误,因此如果有可能,我们只需添加一个检查:

然后,我们需要处理这样一个事实,即您的答案需要是递归的,这使得它稍微复杂一些,但不太难修复:

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

正如在Python2.7之前的注释中所指出的,您可能没有字典理解。为了解决这个问题,
dict()
将使用元组生成器,因此您可以像这样替换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'}}

您可以通过以下方式中的一行执行此操作:

当然,当值不是函数时,这会引发错误,因此如果有可能,我们只需添加一个检查:

然后,我们需要处理这样一个事实,即您的答案需要是递归的,这使得它稍微复杂一些,但不太难修复:

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

正如在Python2.7之前的注释中所指出的,您可能没有字典理解。为了解决这个问题,
dict()
将使用元组生成器,因此您可以像这样替换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'}}

@TimPietzcker我意识到,当我发布时,更新了这两个方面的答案。语法中还有一个冒号:
{key:value for key,value in dict.items()}
@EmilIvanov实际上,如果您使用的是以前的版本,那么它只是元组生成器表达式的一个微不足道的替换,
dict()
,例如:
{x:y for…}
会变成
dict((x,y)for…
。我不知道我怎么能不把结肠放在那里。谢谢你指出这一点。修正了。这是解决我问题的好办法。非常感谢@TimPietzcker我意识到,当我发布时,更新了这两个方面的答案。语法中还有一个冒号:
{key:value for key,value in dict.items()}
@EmilIvanov实际上,如果您使用的是以前的版本,那么它只是元组生成器表达式的一个微不足道的替换,
dict()
,例如:
{x:y for…}
会变成
dict((x,y)for…
。我不知道我怎么能不把结肠放在那里。谢谢你指出这一点。修正了。这是解决我问题的好办法。非常感谢!