python - 如何在 python 中避免使用 eval

标签 python eval

我有一款游戏已经开发了一段时间了。核心是 C++,但我使用 Python 来编写脚本和攻击/状态效果/项目等。

我已经把自己编码到了一个角落,我必须使用 eval 来获得我想要的行为。它是这样产生的:

我有一个 xml 文档,用于规范攻击,如下所示:

<Attack name="Megiddo Flare" mp="144" accuracy="1.5" targetting="EnemyParty">
    <Flags>
        <IgnoreElements/>
        <Unreflectable/>
        <ConstantDamage/>
        <LockedTargetting/>
    </Flags>
    <Components>
        <ElementalWeightComponent>
            <Element name="Fire" weight="0.5"/> 
        </ElementalWeightComponent>
        <ConstantDamageCalculatorComponent damage="9995" index="DamageCalculatorComponent"/>    
    </Components>
</Attack>

我用 python 解析这个文件,并构建我的攻击。每个攻击由任意数量的组件组成,以实现不同的行为。在这个攻击的例子中,我实现了 DamageCalculatorComponent,告诉 python 使用 ConstantDamage 变体。我在脚本文件中实现了所有这些组件。这对于我经常使用的组件类型来说非常好。在某些攻击中,该攻击将是使用该特定组件变体的唯一攻击。我希望能够在 xml 文件中指定 Component 类,而不是将组件添加到我的脚本文件中。

例如,如果我要实现《最终幻想》中的经典白风攻击(根据攻击者的生命值恢复团队生命值)

<Attack name="White Wind" mp="41" targetting="AnyParty">
    <Flags>
        <LockedTargetting/>
    </Flags>
    <Components>
        <CustomComponent index="DamageCalculatorComponent">
            <![CDATA[
                class WhiteWindDamageComponent(DamageCalculatorComponent):
                    def __init__(self, Owner):
                        DamageCalculatorComponent.__init__(self, Owner)

                    def CalculateDamage(self, Action, Mechanics):
                        Dmg = 0
                        character = Action.GetUsers().GetFirst()
                        SM = character.GetComponent("StatManagerComponent")
                        if (SM != None):
                            Dmg = -SM.GetCurrentHP()
                        return Dmg
                return WhiteWindDamageComponent(Owner)
            ]]>     
        </CustomComponent>
    </Components>
</Attack>

我想知道是否有更好的方法来做到这一点?我能看到的唯一其他方法是将每个可能的组件变体定义放入我的 python 文件中,并展开我的组件创建者以检查其他变体。对于一次性使用的组件来说似乎有点浪费。是否有更好/更安全的替代方案来动态生成类型,或者可能是我没有看到的另一种解决方案?

提前致谢

最佳答案

内联 Python 很糟糕,因为

  • Python 源代码编辑器无法理解您的源代码文件,您将错过语法突出显示

  • 所有其他工具,例如 pylint,可用于检查和验证源代码也将失败

替代方案

在元素<CustomComponent index="DamageCalculatorComponent">

...添加参数script :

<CustomComponent index="DamageCalculatorComponent" script="damager.py">

然后添加文件damager.py文件系统中的某处。

按照此处所述加载它:What is an alternative to execfile in Python 3?

在您的主游戏引擎代码中,从加载的系统模块中构造类,例如:

 damager_class = sys.modules["mymodulename"].my_factory_function()

所有 Python 模块必须共享某种约定的类名/入口点函数。

如果你想拥有真正的可插拔架构,请使用 Python Eggs 和 setup.py入口点

示例

关于python - 如何在 python 中避免使用 eval,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10357119/

相关文章:

javascript - 如何动态调用 JavaScript 对象的方法

Python:读取 12 位压缩二进制图像

python 如何在Windows系统中构建scrapy.exe、pip.exe、virtualenv.exe等exe文件?

python - 我如何委托(delegate)给父类(super class)的 __add__ 方法?

PHP:需要一个 eval() 的替代方法来动态构建多维数组

javascript - 在这种情况下 eval() 是邪恶的吗?

python - 在魔术方法中键入 'other' 的提示?

python - Homebrew pyenv安装报错dyld : Library not loaded:/usr/local/opt/readline/lib/libreadline. 7.dylib

javascript - 获取对 JavaScript 中 eval() 期间创建的局部变量的引用

java - 为什么 eval 类给我一个从 int 到 double 的转换错误?