8

我想创建一个 python 目录,其值将单独评估。

因此,例如,在以下非工作示例中,我定义

a = {'key1': 'value1', 'key2': 42, 'key3': foo(20)}

例如

def foo(max):
    """Returns random float between 0 and max."""
    return max*random.random()

在处理我想要的dict之后

a_processes = {'key1': 'value1', 'key2': 42, 'key3': 12.238746374}

该示例不起作用,因为 key 的值key3被立即评估,并且foo(20)不可调用。它可以工作的方式是使用类似的东西

a = {'key1': 'value1', 'key2': 42, 'key3': foo}

但这里foo会错过它的论点。处理此问题的一种方法是按以下方式定义字典

a = {'key1': 'value1', 'key2': 42, 'key3': [foo, 20]}

采用以下处理方案

a_processed = dict([k,process(v)] for k,v in a.items())

其中process是一个有意义的函数,它检查它的参数是否是一个列表,或者第一个元素是否是一个可调用的,它会被剩余的参数调用。

我的问题是关于实现我的基本想法的更好方法/想法?

4

2 回答 2

9

使用functools.partial()创建一个可调用对象,它将一组参数应用于另一个可调用对象:

from functools import partial

a = {'key1': 'value1', 'key2': 42, 'key3': partial(foo, 20)}

现在该key3值是一个可调用对象;a['key3']()将依次调用foo(20)并返回结果。

您仍然需要“处理”这本字典(使用以下callable()功能进行测试:

{k: v() if callable(v) else v for k, v in a.iteritems()}

当然。如果您使用的是 Python 3,请a.items()改用。

设置让您可以根据functools.partial需要添加其他参数(只要foo()支持它们):

a['key3']('additional', arguments='accepted')

甚至可以创建一个在访问键时自动执行此操作的字典子类:

def CallablesDict(dict):
    def __getitem__(self, key):
        value = super(CallablesDict, self).__getitem__(key)
        return value() if callable(value) else value

然后定义a为:

a = CallablesDict({'key1': 'value1', 'key2': 42, 'key3': partial(foo, 20)})

print a['key3']  # calls foo(20)
于 2013-01-30T17:48:53.413 回答
6

我经常在这里使用无参数lambda,只是因为我喜欢这种语法:

>>> def foo(x):
...     return x*100
... 
>>> a = {'key1': 'value1', 'key2': 42, 'key3': lambda: foo(20)}
>>> a
{'key3': <function <lambda> at 0x96ae80c>, 'key2': 42, 'key1': 'value1'}
>>> {k: v() if callable(v) else v for k,v in a.iteritems()}
{'key3': 2000, 'key2': 42, 'key1': 'value1'}
于 2013-01-30T17:50:19.243 回答