1

PythonでPythonスクリプト内にPythonコードを作成し、それを実行/テストする方法はありますか?

私の関数には次のような形式があります(例として)

def f(n):
    if n<=3: return [0, 0, 6, 12][n]
    return 2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4)

しかし、これらの種類の関数を動的に作成し(または任意の関数)、実行時に出力をテストできるようにしたい(この関数をスクリプトにコピーして貼り付けてから手動でテストするのではなく)。

これが理にかなっているかどうかわからない場合は、必要に応じて詳細を尋ねてください。私はすでにevalとexecを調べましたが、関数定義全体、1+2などの基本的なステートメントだけでそれらを機能させることができませんでした。

4

3 に答える 3

4

この種のことを行うにはいくつかの方法があります。

「言語の外に出る」ことなく関数を記述できる場合は、Blenderの答えのように、ローカル関数を定義して返すことができます。これは通常、新しい関数を定義する必要があると思うときに必要なものです(Blenderの例を借りています)。

def make_func(a, b):
    def f(n):
        return n**a + b
    return f

場合によっては、さらにうまく実行して、関数をデータとして表すことができます。たとえば、どのようにして任意の多項式関数を作成しますか?まあ、あなたはする必要はありません。係数と値のリストを取り、それを評価する一般的な多項式関数を持つことができます。その後、あなたがする必要があるのは係数リストを作成することです。

実際、これはあなたがここで欲しいものだと思います。あなたが言うように:

2 * f(n-1)-4 * f(n-2)-5 * f(n-3)+ 15 * f(n-4)1分を返すか、f(n-1)を返します。 + 3 * f(n-2)別、またはf(n-1)+ f(n-2)+ f(n-3)+ f(n-4)+ 5 * f(n-5)私が必要としているもの。

これは間違いなく係数のリストとして表すことができます。

def make_recursive_func(coefficients, baseval):
    def f(n):
        if n < len(coefficients): return baseval[n]
        return sum(coefficient * f(n-i-1) for i, coefficient in enumerate(coefficients))
    return f

eval_recursive_func(coefficients, baseval)ただし、返された関数で行うのが、すぐに呼び出してから忘れるだけの場合は、単一の関数を作成する方がおそらくさらに簡単です。

まれにですが、決してではありませんが、実際にコードをその場で実行する必要がある場合があります。ひまんしゅが言うようにevalexecそして友達はこれを行う方法です。例えば:

newcode = '''
def f(n):
    if n<=3: return [0, 0, 6, 12][n]
    return 2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4)
'''
exec(newcode)

これで、f関数が定義されました。これを実行した場合とまったく同じです。

def f(n):
    if n<=3: return [0, 0, 6, 12][n]
    return 2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4)

Py3とPy2は少し異なり、実行するコンテキストや、実行するか、評価するか、コンパイルするか、インポートのように扱うかなどによって異なります。ただし、これが基本的な考え方です。

2番目ではなく1番目を書きたい理由がわからない場合は、これは必要ありません。

そして、その場で正しい文字列を生成する方法がわからない場合は、これを行うべきではありません。

また、Ignacio Vazquez-Abramsが指摘しているように、これらの関数をユーザー入力から構築できる場合は、通常は繰り返しコンパイルしてASTを実行することにより、安全であることを検証するために何かを行う必要があります。

最後に、さらにまれに、newモジュール(および/またはinspect)を使用して、他の関数オブジェクトのビットから(または手作りのバイトコードから)その場で新しい関数オブジェクトを作成する必要があります。しかし、それを行う方法を知る必要がある場合は、おそらくすでにその方法を知っています。

于 2012-12-10T04:44:29.360 に答える
3

関数が類似している場合は、別の関数を使用して関数を作成できます。

def make_func(a, b):
    def f(n):
        return n**a + b

    return f

を使用するとmake_func、この関数定義が変換されます。

def g(n):
     return n**2 + 1

これだけに:

g = make_func(2, 1)

あなたの場合、このようなものが機能するはずです:

def create_f(start_condition, vars, coeff_pairs):
    def x(n):
        if n <= start_condition:
            return vars[n]

        result = 0.0

        for coeff, shift in coeff_pairs:
            result += coeff * x(n + shift)

        return result

    return x

そして、あなたはそれを次のように呼ぶことができます:

f = create_f(3, [0, 0, 6, 12], [(2, -1), (-4, -2), (-5, -3), (15, -4)])

出力は、ハードコードされた関数の出力と一致します。

于 2012-12-10T04:36:33.523 に答える
2

それは完全に理にかなっています。Pythonには、この目的のために明示的にモジュールのセットもあります。ただし、関数を実行する前に、ASTをウォークしてノードを検証し、誰かがそこに忍び込んでいないことを確認してos.system('rm -rf /')ください。

于 2012-12-10T04:38:42.310 に答える