Reputation: 23
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
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
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