Reputation: 31
I'd like to define a dictionary to use as a template and upon getting of the value, have it execute a function
d = {'choice': random.choice([1, 2, 3, 4, 5])
>>> d.get('choice')
3
>>> d.get('choice')
1
>>> d.get('choice')
5
Ultimately, I'd like to have a list of these dictionary templates that I would loop over, and each time the dictionary is iterated upon, for certain fields (like choice
above) I would like to have a random value out of the list
Upvotes: 2
Views: 55
Reputation: 123491
You can subclass the built-in dict
class and specialize it by overriding its __getitem__()
method to do what's needed.
In the example code below the function to call, arguments to pass it, and an id are all passed to the class initializer when an instance of the class is created — making it very generic because you can create separate instances that will call a different function (or passing the same one a different set of arguments or give it a different id).
Instance of the derived class can be otherwise be initialized and used like a normal dictionary.
class FuncDict(dict):
def __init__(self, *args, func_info=None, **kwargs):
if not func_info or len(func_info) != 3:
raise RuntimeError(
'A "func_info" keyword argument of three elements is required')
super().__init__(*args, **kwargs) # Initialize base class instance.
self.func, self.func_args, self.func_id = func_info # Save.
def __getitem__(self, key):
return (self.func(self.func_args) if key == self.func_id
else super().__getitem__(key))
if __name__ == '__main__':
import random
# fd = FuncDict([('foobar', 42)], func_info=(random.choice, [1,2,3,4,5], 'choice'))
fd = FuncDict(foobar=42, func_info=(random.choice, [1,2,3,4,5], 'choice'))
print(fd['choice']) # -> Some value from 1 to 5.
print(fd['foobar']) # -> 42
Upvotes: 0
Reputation: 1153
One other thing you could do is just have the function be the value in the dictionary. So it would look like:
l = [1, 2, 3]
d = {'choice': random.choice}
and then to actually get the number you can say d['choice'](l)
. If you need more flexibility you can define your own lambda/wrapper functions.
Upvotes: 0
Reputation: 5397
Create a new class that inherits from dict, then override __getitem__
. For instance:
import random
class MyDict(dict):
def __getitem__(self, key):
if key == "choice":
return random.choice(super().__getitem__(key))
else:
return super().__getitem__(key)
d = MyDict(choice=[1,2,3,4,5],something_else=1)
print(d["choice"]) # outputs a random value from 1 to 5
print(d["something_else"]) # still outputs 1
This can be extended to use a second dict of templates used for custom behavior in __getitem__
depending on the key.
Upvotes: 2