I would like to create a python directory whose values are to be evaluated separately.
So, for example, in the following non-working example I define
a = {'key1': 'value1', 'key2': 42, 'key3': foo(20)}
for which e.g.
def foo(max):
"""Returns random float between 0 and max."""
return max*random.random()
and after processing of the dict I want to have e.g.
a_processes = {'key1': 'value1', 'key2': 42, 'key3': 12.238746374}
The example does not work since the value of key key3
is immediately evaluated, and foo(20)
is no callable. The way it could work would be to use something like
a = {'key1': 'value1', 'key2': 42, 'key3': foo}
but here foo
will miss its arguments. One way to handle this would be to define the dict in the following way
a = {'key1': 'value1', 'key2': 42, 'key3': [foo, 20]}
with the following processing scheme
a_processed = dict([k,process(v)] for k,v in a.items())
in which process
is a meaningful function checking if its argument is a list, or if the first element is a callable which gets called with the remaining arguments.
My question is about a better way/idea to implement my basic idea?
Use the functools.partial()
to create a callable that'll apply a set of arguments to another callable:
from functools import partial
a = {'key1': 'value1', 'key2': 42, 'key3': partial(foo, 20)}
Now the key3
value is a callable object; a['key3']()
will in turn call foo(20)
and return the result.
You'd still need to 'process' this dictionary (testing with the callable()
function:
{k: v() if callable(v) else v for k, v in a.iteritems()}
of course. If you are using Python 3, use a.items()
instead.
A functools.partial
setup let's you add additional arguments as needed (provided foo()
supports them):
a['key3']('additional', arguments='accepted')
You could even create a dictionary subclass that does this automatically when accessing a key:
def CallablesDict(dict):
def __getitem__(self, key):
value = super(CallablesDict, self).__getitem__(key)
return value() if callable(value) else value
then define a
as:
a = CallablesDict({'key1': 'value1', 'key2': 42, 'key3': partial(foo, 20)})
print a['key3'] # calls foo(20)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With