9

我正在使用 pygame 和 box2d 编写游戏引擎,并且在角色构建器中,我希望能够编写将在 keydown 事件上执行的代码。

我的计划是在角色生成器中添加一个文本编辑器,让您编写类似于以下内容的代码:

if key == K_a:
    ## Move left
    pass
elif key == K_d:
    ## Move right
    pass

我将文本编辑器的内容作为字符串检索,并且我希望代码在 Character 的这个方法中的一个方法中运行:

def keydown(self, key):
    ## Run code from text editor

最好的方法是什么?

4

4 回答 4

25

您可以使用该eval(string)方法来执行此操作。

定义

eval(code, globals=None, locals=None)
该代码只是标准的 Python 代码——这意味着它仍然需要正确缩进。

全局变量可以具有自__builtins__定义定义,这对于安全目的可能很有用。

例子

eval("print('Hello')")

将打印hello到控制台。您还可以指定要使用的代码的局部和全局变量:

eval("print('Hello, %s'%name)", {}, {'name':'person-b'})

安全问题

不过要小心。将执行任何用户输入。考虑:

eval("import os;os.system('sudo rm -rf /')")

有很多方法可以解决这个问题。最简单的方法是执行以下操作:

eval("import os;...", {'os':None})

这将引发异常,而不是擦除您的硬盘驱动器。虽然您的程序是桌面程序,但如果人们重新分发脚本,这可能是一个问题,我想这是有意的。

奇怪的例子

eval这是一个相当奇怪的使用示例:

def hello() : print('Hello')
def world() : print('world')
CURRENT_MOOD = 'happy'

eval(get_code(), {'contrivedExample':__main__}, {'hi':hello}.update(locals()))

这在 eval 行上的作用是:

  1. 给当前模块另一个名字(它变成contrivedExample脚本)。消费者现在可以打电话contrivedExample.hello()了。)
  2. 它定义hi为指向hello
  3. 它将该字典与执行模块中的当前全局变量列表相结合。

失败

事实证明(感谢评论者!)您实际上需要使用该exec语句。大哎呀。修改后的示例如下:


exec定义

(这看起来很熟悉!) Exec 是一个语句:
exec "code" [in scope] 其中 scope 是本地和全局变量的字典。如果未指定,则在当前范围内执行。

该代码只是标准的 Python 代码——这意味着它仍然需要正确缩进。

exec例子

exec "print('hello')"

将打印hello到控制台。您还可以指定要使用的代码的局部和全局变量:

eval "print('hello, '+name)" in {'name':'person-b'}

exec安全问题

不过要小心。将执行任何用户输入。考虑:

exec "import os;os.system('sudo rm -rf /')"

打印声明

正如评论者所指出的,print是 3.0 之前的所有 Python 版本中的声明。在 2.6 中,可以通过键入来更改行为from __future__ import print_statement。否则,使用:

print "hello"

代替 :

print("hello")
于 2009-06-18T20:57:11.093 回答
2

正如其他人指出的那样,您可以将文本加载到字符串中并使用exec "codestring". 如果已经包含在文件中,使用execfile将避免加载它。

一个性能说明:您应该避免多次执行代码,因为解析和编译 python 源代码是一个缓慢的过程。IE。没有:

def keydown(self, key):
    exec user_code

您可以通过将源代码编译为代码对象来稍微改进这一点(使用compile()并执行它,或者更好的是,通过构建一个您保留的函数,并且只构建一次。要么要求用户编写“def my_handler(args.. .)”,或者自己添加它,然后执行以下操作:

user_source = "def user_func(args):\n" + '\n'.join("    "+line for line in user_source.splitlines())

d={}
exec user_source in d
user_func = d['user_func']

然后后来:

if key == K_a:
   user_func(args)
于 2009-06-18T21:12:28.783 回答
0

您可以使用eval()

于 2009-06-18T20:58:18.593 回答
0

评估或执行。在编程之前,您绝对应该阅读 Python 库参考。

于 2009-06-18T20:58:38.093 回答