我目前对于如何以有效的方式做到这一点是空白的。我想过使用对象,但我不知道他们在这种情况下可以提供什么帮助。有什么想法吗?
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!
答案 0 :(得分: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()
会生成一个元组生成器,所以你可以像这样替换一个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'}}