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