Clay Reakes
Clay Reakes

Reputation: 23

How to call a dictionary item that can be an integer or function?

I am trying to come up with a code that will do statistical analysis of a unit from a table top game for personal use. I am using dictionaries to store unit data, and I have ran into an issue where the damage from an attack can either be an integer value, or the result of a dice roll "d6"

I have made a function that takes a value of d6 and evaluates it as d(6) then runs the simple calculation to determine the average number of shots, 3.5. For convenience reasons I would like to be able to keep "d(6)' in the dictionary instead of converting to the 3.5 manually for each unit I want to put in.

In a very stripped down example of the unit dictionary,

unit = {'damage':1}

or

unit = {'damage':'d(6)'}

I am looking for a way to check the "damage" call for if the value is an integer or string, and then if it is a string, strip the quotes from it and evaluate it as a function. I'm not having much luck in my search, as I don't really know what I'm searching for.

Upvotes: 2

Views: 65

Answers (2)

Serge Ballesta
Serge Ballesta

Reputation: 149125

It a close to a matter of opinion. You can either be consistent in the content of the dictionary as suggested by @Sayse, or test it at usage time. But in either case you should not use a string but a callable to call it directly without using the frowned upon eval:

def process (dic, key):
    return dic[key]() if callable(dic[key]) else dic[key]
...
damage = process(unit, 'damage')

Python makes it easy to use parameterized functions. For example if you want to return the value of d(6), you can use a lambda:

unit = {'damage': (lambda : d(6))}

or functools.partial:

unit = {'damage': functools.partial(d, 6)}

Upvotes: 0

Sayse
Sayse

Reputation: 43320

Make every single value of your dictionary consistent and return a lambda function that you can call, the d function will not be evaluated until it is called.

>>> unit = {'damage': lambda: 1, 'b': lambda: d(6) }
>>> unit['damage']()
1
>>> unit['b']()
result of d(6)

Upvotes: 3

Related Questions