3

Kann man innerhalb eines Dekorators auf Funktionsattribute zugreifen? Betrachten Sie unter Stück Code.Zugreifen auf Funktionsattribute in Dekoratoren

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



    return wrap 


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


fun1.status="foo" 
fun1() 

erwartete ich die Ausgabe zu sein:

foo 
bar 

Aber ich bekomme die folgenden Fehler:

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' 

Gibt es eine Möglichkeit, diese Arbeit zu machen, da

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


fun1.status="foo" 

a=fun1 

print(a.status) 
a() 
print(a.status) 

Ausgänge:

foo 
bar 

Wie erwartet.

Antwort

1

Dank des Dekorateur, der globale Name fun1 das Ergebnis Dekoration gebunden, so an das verschachtelten wrap() Funktionsobjekt. Inside wrap() jedoch bezieht sich a auf das Original, ausgepackte Funktion Objekt.

So haben Sie zwei verschiedene Funktionsobjekte, und jedes kann Attribute haben; Sie sind nicht die gleichen Objekte. fun1.status ist ein anderes Attribut als a.status.

print(wrap.status) 

Demo:

>>> 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

def deco (a): def wickeln(): print (fun1

Sie das gleiche Objekt wie fun1 in der Dekorateur als wrap zugreifen können. Status) a() drucken (fun1.status) zurückspulen @deco def fun1(): fun1.status = "bar" fun1.status = "foo" fun1() –

+0

der obige Code funktioniert auch. Interessant –

+0

@SudhanNadar: Ja, weil Sie dann den globalen Namen 'fun1' referenzieren, auf den der Dekorateur abzielte. Aber jetzt bist du an diese * eine Funktion gebunden, die du geschmückt hast *, du kannst den Dekorator nicht für eine andere Funktion 'fun2' verwenden und erwarten, dass du Zugriff auf die Attribute dieses zweiten Funktionsobjekts erhältst, wenn du es aufruft. 'wrap' wird immer der richtige Bezug zum Dekorationsergebnis sein. –