1

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

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!

4

1 回答 1

8

你可以用字典理解中的一行来做到这一点:

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

当然,当值不是函数时,这会抛出错误,所以如果有可能,我们可以简单地使用内置callable()函数添加检查:

{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要存储在dictthis 函数中的属性或方法,则将在此函数上运行,这可能会导致问题。我建议更改该属性或方法的名称,或将检查替换为isinstance(dict).

我还想指出,对于rand_int返回字符串'yes'或的误导性函数名称'no'可能与它得到的一样糟糕。通常,您也希望True/False在这些情况下。

如评论中所述,在 Python 2.7 之前,您可能没有字典理解。为了解决这个问题,dict()将使用元组生成器,因此您可以像这样替换 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'}}
于 2012-05-09T10:32:04.443 回答