9

私は pygame と box2d を使用してゲーム エンジンを作成しています。キャラクター ビルダーでは、キーダウン イベントで実行されるコードを記述できるようにしたいと考えています。

私の計画は、キャラクター ビルダーにテキスト エディターを用意して、次のようなコードを記述できるようにすることでした。

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 /')"

ステートメントを印刷

コメンターによっても指摘されているように、print3.0 より前のすべてのバージョンの Python でのステートメントです。2.6 では、 と入力して動作を変更できますfrom __future__ import print_statement。それ以外の場合は、次を使用します。

print "hello"

それ以外の :

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

As others have pointed out, you can load the text into a string and use exec "codestring". If contained in a file already, using execfile will avoid having to load it.

One performance note: You should avoid execing the code multiple times, as parsing and compiling the python source is a slow process. ie. don't have:

def keydown(self, key):
    exec user_code

You can improve this a little by compiling the source into a code object (with compile() and exec that, or better, by constructing a function that you keep around, and only build once. Either require the user to write "def my_handler(args...)", or prepend it yourself, and do something like:

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

Then later:

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

使用できますeval()

于 2009-06-18T20:58:18.593 に答える
0

eval または exec. プログラミングの前に、必ず Python ライブラリ リファレンスを読む必要があります。

于 2009-06-18T20:58:38.093 に答える