5

関数を考えると

def f():
    x, y = 1, 2 
    def get():
        print 'get'
    def post():
        print 'post'

ローカルの get() および post() 関数にアクセスして呼び出す方法はありますか? 上記で定義された関数 f() でそのように機能する関数を探しています:

>>> get, post = get_local_functions(f)
>>> get()
'get'

そのようなローカル関数のコード オブジェクトにアクセスできます。

import inspect
for c in f.func_code.co_consts:
    if inspect.iscode(c):
        print c.co_name, c

その結果、

get <code object get at 0x26e78 ...>
post <code object post at 0x269f8 ...>

しかし、実際の呼び出し可能な関数オブジェクトを取得する方法がわかりません。それは可能ですか?

ご協力いただきありがとうございます、

意思。

4

4 に答える 4

4

あなたはそれを行うのにかなり近いです-newモジュールが欠けているだけです:

import inspect
import new

def f():
    x, y = 1, 2
    def get():
        print 'get'
    def post():
        print 'post'

for c in f.func_code.co_consts:
    if inspect.iscode(c):
        f = new.function(c, globals())
        print f # Here you have your function :].

しかし、なぜわざわざ?クラスの方が使いやすいんじゃない?とにかく、インスタンス化は関数呼び出しのように見えます。

于 2009-08-05T21:15:39.100 に答える
2

execを使用してコードオブジェクトを実行できます。たとえば、上記のようにfを定義した場合、

exec(f.func_code.co_consts[3])

与えるだろう

get

出力として。

于 2009-08-05T17:57:21.310 に答える
2

Python の他のオブジェクトと同じように、関数を返すことができます。

def f():
    x, y = 1, 2 
    def get():
        print 'get'
    def post():
        print 'post'
    return (get, post)


get, post = f()

お役に立てれば!

ただし、get() または post() で 'x' および 'y' 変数を使用する場合は、それらをリストにする必要があることに注意してください。

次のようなことをすると:

def f():
    x = [1]
    def get():
        print 'get', x[0]
        x[0] -= 1
    def post():
        print 'post', x[0]
        x[0] += 1
    return (get, post)

get1, post1 = f()
get2, post2 = f()

get1 と post1 は、get2 と post2 とは異なる「x」リストを参照します。

于 2009-08-05T17:43:38.137 に答える
1

関数 f() が実行される前は、内部関数オブジェクトは存在しません。それらを取得したい場合は、自分で構築する必要があります。関数のスコープから変数をキャプチャするクロージャーである可能性があり、おそらくインタープリターの実装の詳細と見なされるべきオブジェクトをいじる必要があるため、これは間違いなく重要です。

繰り返しを少なくして関数を収集したい場合は、次のいずれかの方法をお勧めします。

a) 関数をクラス定義に入れ、そのクラスへの参照を返すだけです。名前でアクセスされる関連する関数のコレクションは、クラスのような匂いがします。

b) 関数を登録するためのメソッドを持つ dict サブクラスを作成し、それをデコレータとして使用します。

このコードは次のようになります。

class FunctionCollector(dict):
    def register(self, func):
        self[func.__name__] = func

def f():
    funcs = FunctionCollector()
    @funcs.register
    def get():
        return 'get'
    @funcs.register
    def put():
        return 'put'
    return funcs

c) locals() を調べて、inspect.isfunction で関数を除外します。(通常は良い考えではありません)

于 2009-08-05T20:45:10.317 に答える