2016-11-09 13 views
0

.func_codeのような内部オブジェクトを使用してコードオブジェクトを保持すると、というコードが呼び出されます。このコードは何ですか?単純に、それは動作しません呼び出す:Pythonでコードオブジェクトを呼び出す方法

def f(): 
    def g(): 
    return 3 
    f.x = g 
    return g() + 1 

f.func_code.co_consts[1] 

結果:ユニットテストネストされた関数のようなとき

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'code' object is not callable 

def f(): pass 

f.func_code() 

結果は、これは便利になることができます

<code object g at 0x7f123991b930, file "<stdin>", line 2> 

もちろん、このpiコードのeceにはまだ文脈などが必要ですが、それは私の質問ではありません。

+1

「評価する」または「実行する」ことができます。 – vaultah

+0

新しい関数を作成し、その関数に 'func_code'を割り当てることができます。そのようなことをしている[この回答](http://stackoverflow.com/a/3454053/355230)の 'add_self()'関数を見てください。 – martineau

+0

@vaultahそれはまさに私にとっての解決策です!あなたはそれをAに入れて気になりますので、私はそれを受け入れることができます、ちょうどこのQを正しく閉じるために? – Alfe

答えて

0

eval()またはexecです。それらは自由変数がある場合

(例えば、外側の関数のネストされた関数の前に定義されたローカル変数を持つネストされた関数のコードのため)、これは(eval又はexecこの場合TypeErrorを上げる)を直接可能ではありません。

また、コードに引数を渡すことは直接できません。

しかし、オンザフライで指定されたコードのラッピング関数を作成できます。通常、この関数は(f(…)を使用して)呼び出すことができ、通常の方法で引数を渡します。これはtypes.FunctionTypeを使用して行われます。 フリーの変数への参照を達成するには、Pythonが期待している正しいデータ型を得るためにトリックを使用する必要があります。例については、以下のコードを参照してください。

def f(v1=1): 
    v2 = 2 
    def g(v3=4): 
    return v1 + v2 + v3 + 8 
    return g() + 16 

def freeVar(val): 
    def nested(): 
    return val 
    return nested.__closure__[0] 

def nested(outer, innerName, **freeVars): 
    if isinstance(outer, (types.FunctionType, types.MethodType)): 
    outer = outer.func_code 
    for const in outer.co_consts: 
    if isinstance(const, types.CodeType) and const.co_name == innerName: 
     return types.FunctionType(const, globals(), None, None, tuple(
      freeVar(freeVars[name]) for name in const.co_freevars)) 

nestedG = nested(f, 'g', v1=1, v2=2) 
print nestedG(4) # will print 15 
関連する問題