我想创建一个python目录,其值将单独计算.
因此,例如,在我定义的以下非工作示例中
a = {'key1': 'value1', 'key2': 42, 'key3': foo(20)}
Run Code Online (Sandbox Code Playgroud)
例如
def foo(max):
"""Returns random float between 0 and max."""
return max*random.random()
Run Code Online (Sandbox Code Playgroud)
在处理dict之后我想要有例如
a_processes = {'key1': 'value1', 'key2': 42, 'key3': 12.238746374}
Run Code Online (Sandbox Code Playgroud)
该示例不起作用,因为key的值key3立即被评估,并且foo(20)不可调用.它的工作方式是使用类似的东西
a = {'key1': 'value1', 'key2': 42, 'key3': foo}
Run Code Online (Sandbox Code Playgroud)
但这里foo会错过它的论点.处理此问题的一种方法是以下列方式定义dict
a = {'key1': 'value1', 'key2': 42, 'key3': [foo, 20]}
Run Code Online (Sandbox Code Playgroud)
使用以下处理方案
a_processed = dict([k,process(v)] for k,v in a.items())
Run Code Online (Sandbox Code Playgroud)
其中process有一个有意义的函数检查它的参数是否是一个列表,或者第一个元素是一个可调用的函数,它被剩余的参数调用.
我的问题是关于实现我的基本想法的更好的方式/想法?
使用functools.partial()创建一个callable,它将一组参数应用于另一个callable:
from functools import partial
a = {'key1': 'value1', 'key2': 42, 'key3': partial(foo, 20)}
Run Code Online (Sandbox Code Playgroud)
现在key3值是一个可调用的对象; a['key3']()将依次调用foo(20)并返回结果.
你仍然需要'处理'这个字典(用callable()函数测试:
{k: v() if callable(v) else v for k, v in a.iteritems()}
Run Code Online (Sandbox Code Playgroud)
当然.如果您使用的是Python 3,请a.items()改用.
一个functools.partial安装咱们您根据需要添加额外的参数(提供foo()支持它们):
a['key3']('additional', arguments='accepted')
Run Code Online (Sandbox Code Playgroud)
您甚至可以创建一个字典子类,在访问密钥时自动执行此操作:
def CallablesDict(dict):
def __getitem__(self, key):
value = super(CallablesDict, self).__getitem__(key)
return value() if callable(value) else value
Run Code Online (Sandbox Code Playgroud)
然后定义a为:
a = CallablesDict({'key1': 'value1', 'key2': 42, 'key3': partial(foo, 20)})
print a['key3'] # calls foo(20)
Run Code Online (Sandbox Code Playgroud)
我经常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'}
Run Code Online (Sandbox Code Playgroud)