我的代码中有许多变量,例如STA,INT,AGI和dmg_taken,并希望dmg_taken由用户定义的等式计算。作为概念证明,我使用了eval,其工作原理如下。
unsafe.py
dmg_min = eval(self.rules.all_rules['dmg_min'])
dmg_max = eval(self.rules.all_rules['dmg_max'])
具有等式的外部规则文件看起来像
battle.rules
dmg_min = 2
dmg_max = round(((STR * 1.5) + (AGI * 1.02) + (INT * 1.3)) / 6 )
规则可以是包含程序中使用的任意数量变量的数字或公式 - 有什么更好的方法可以做到这一点?
答案 0 :(得分:0)
我没有遇到过一种完全安全的方法来解决这个问题。
用户定义的方程式可以由python代码中的库用户完成(基本上他们可以在控制代码时做他们想做的事情)
对于外部用户,所有方程式参数都会拆分为变量并以数字形式读取,因此无需进行评估。
修改规则文件
dmg_INT_mult = 0.9
dmg_AGI_mult = 1.2
dmg_STR_mult = 1.2
dmg_INT_add = -.5
dmg_AGI_add = 0
dmg_STR_add = 0
dmg_overall_mult = 0.1667
dmg_overall_add = 0
这些参数用于在battle.py程序中构建等式
# dmg_max = round(
# ((STR + dmg_STR_add) * dmg_STR_mult)
# + ((AGI + dmg_AGI_add) * dmg_AGI_mult)
# + ((INT + dmg_INT_add) * dmg_INT_mult)
# ) * dmg_overall_mult
# + dmg_overall_add
新代码
calc_agi = round((AGI + float(self.rules.all_rules['dmg_AGI_add'])) * float(self.rules.all_rules['dmg_AGI_mult']))
calc_int = round((INT + float(self.rules.all_rules['dmg_INT_add'])) * float(self.rules.all_rules['dmg_INT_mult']))
calc_str = round((STR + float(self.rules.all_rules['dmg_STR_add'])) * float(self.rules.all_rules['dmg_STR_mult']))
dmg_max = round((calc_agi + calc_int + calc_str) * float(self.rules.all_rules['dmg_overall_mult']) + float(self.rules.all_rules['dmg_overall_add']))
这是安全的,因为读入的所有参数都被转换为浮点数,因此任何字符串都会导致异常,并允许最终用户构建相当复杂的方程式。