3

デコレータ内の関数属性にアクセスできますか? 以下のコードを検討してください。デコレータ内の関数属性にアクセスする

def deco(a): 
    def wrap(): 
     print(a.status) 
     a() 
     print(a.status) 



    return wrap 


@deco 
def fun1(): 
    fun1.status="bar" 


fun1.status="foo" 
fun1() 

私は、出力があることが予想:

foo 
bar 

しかし、私は以下のエラーが出ます:

Traceback (most recent call last): 
    File "<pyshell#0>", line 1, in <module> 
    fun1() 
    File "D:\python_projects\test_suite\func_attribute.py", line 3, in wrap 
    print(a.status) 
AttributeError: 'function' object has no attribute 'status' 

def fun1(): 
    fun1.status="bar" 


fun1.status="foo" 

a=fun1 

print(a.status) 
a() 
print(a.status) 
ので、この作品を作るための方法はあります

出力:

foo 
bar 

期待通りです。デコレータへ

答えて

1

おかげで、グローバル名fun1は、ネストされたwrap()関数オブジェクトになるよう、装飾結果にバインドされています。しかしながら、wrap()の内部では、aは、元ののを参照しています。

したがって、の2つの異なる機能オブジェクトがあり、それぞれに属性を持つことができます。それらは同じオブジェクトではありません。 fun1.statusa.statusとは異なる属性です。

あなたはwrapとしてデコレータにfun1と同じオブジェクトにアクセスできます。

print(wrap.status) 

デモ:

>>> def deco(a): 
...  def wrap(): 
...   print(wrap.status) 
...   a() 
...   print(wrap.status) 
...  return wrap 
... 
>>> @deco 
... def fun1(): 
...  fun1.status="bar" 
... 
>>> fun1.status="foo" 
>>> fun1() 
foo 
bar 
+0

デフデコ(A): デフ(ラップ): プリント(FUN1。 ) a() print (): fun1.status = "bar" fun1.status = "foo" fun1() –

+0

上記のコードも機能します。面白い –

+0

@SudhanNadar:はい、デコレータがターゲットとしたグローバルな 'fun1'という名前を参照しています。しかし、あなたが装飾した*関数にバインドされているので、別の関数 'fun2'でデコレータを使用することはできず、呼び出すときに2番目の関数オブジェクトの属性にアクセスすることを期待します。 'wrap'は常にデコレーション結果の正しい参照になります。 –

関連する問題