如何在python中使用eval

时间:2012-04-27 20:04:40

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

例如,如果我要实施最终幻想中的经典白风攻击(通过攻击者的HP数量恢复团队HP)

<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>

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

提前致谢

1 个答案:

答案 0 :(得分:2)

内联Python很糟糕,因为

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

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

<强>替代

在元素<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 egg和setup.py入口点

示例