2017-11-30 5 views
-1

のスコープ内の変数を変更することができます。あなたは以下のデコレータの例を見てみましょう飾ら機能

import functools 

def my_decorator(func): 
    my_var = 1 

    @functools.wraps(func) 
    def wrapper(*args, **kwargs): 
     print my_var 
     return func(*args, **kwargs) 

    return wrapper 

@my_decorator 
def my_func(s): 
    print s 

はグローバルスコープでmy_varにアクセスして変更する方法はありますか?

私はmy_varへの参照が表示されていない、まだ私はそれはそれはprint my_varを呼び出すようmy_funcでアクセスできるように持っていることを知っているglobals()[ 'my_func' ]を使用して、ラップされた機能の中に探しています。

さらに、装飾された機能ごとにmy_varという単一インスタンスが必要です。

+1

いいえ、簡単に。そして、どんな試みも壊れやすく、読むのが難しいです。 – jszakmeister

+0

「非ローカルmy_var」を意味しますか?これはPython 2または3ですか? – Ryan

+0

@RyanこれはPython 2.7です。 – JDN

答えて

0

juanpa.arrivillagaはコメントで示した@ように、これは自由変数のルックアップによって可能であり、ここで示したように、クロージャオブジェクトを機能するように結合:

i = my_func.func_code.co_freevars.index('my_var') 
my_var = my_func.func_closure[i].cell_contents 

掲載の質問はそうmy_var、不変オブジェクトを使用しています元の変数が変更されず、再割り当てされませんでした。これはmy_varが変更可能な場合にのみ機能します。

より良い解決策は、この変数をラップされた関数の属性として含めることです。@functools.wrapsデコレータは、他のすべての属性とともにラッパー関数にコピーされます。ただし、変更するためには変更可能なオブジェクトにするにはまだmy_varが必要です。上記のここに示したの

例:

import functools 

def my_decorator(func): 
    my_var = func.my_var = {} 

    @functools.wraps(func) 
    def wrapper(*args, **kwargs): 
     print my_var 
     return func(*args, **kwargs) 

    return wrapper 

@my_decorator 
def my_func(s): 
    print s 

my_func("First call") 
my_func.my_var[ 'Testing' ] = '123' 
my_func("Second call") 

出力:

{} 
First call 
{'Testing': '123'} 
Second call 
関連する問題