Kann ich mit einem Decorator den lokalen Bereich einer Funktion in Python verändern?

8

Gibt es eine Möglichkeit, einen Dekorateur so zu schreiben, dass das Folgende funktioniert?

%Vor%

EDIT: von Anwser verschoben

Als Antwort auf hops "warum?": Syntax Zucker / DRY.

Es geht nicht um Caching, es geht darum, z (und z1, z2, z3, ...) basierend auf den Werten von x & amp; y.

Ich habe viele Funktionen, die verwandte Dinge tun, und ich möchte nicht schreiben

%Vor%

am Anfang jeder einzelnen Funktion - ich werde mich irgendwo irren. Wenn dies c wäre, würde ich das mit cpp machen (wenn das Lisp war, würde ich das mit Makros machen ...), aber ich wollte sehen, ob Dekorateure dasselbe tun könnten.

Wenn es hilft, würde ich den Decorator mit ziemlicher Sicherheit "precalculate_z" nennen und es wäre sicherlich kein Teil einer öffentlichen API.

Ich könnte wahrscheinlich einen ähnlichen Effekt durch die Verwendung der Klasseninfrastruktur bekommen, aber ich wollte sehen, ob es mit rohen Funktionen machbar ist.

    
Toby White 26.02.2009, 16:03
quelle

7 Antworten

11

Echo Hop Antwort

  1. Tu es nicht.
  2. Im Ernst, tu das nicht. Lisp und Ruby sind geeignetere Sprachen für das Schreiben Ihrer eigenen benutzerdefinierten Syntax. Verwenden Sie eine von denen. Oder finden Sie einen saubereren Weg, dies zu tun
  3. Wenn Sie müssen, möchten Sie dynamische Bereichsvariablen, nicht lexikalisch.

Python verfügt nicht über dynamisch beschränkte Variablen, aber Sie können es simulieren. Hier ist ein Beispiel, das es simuliert, indem es eine globale Bindung erstellt, aber den vorherigen Wert beim Beenden wiederherstellt:

Ссылка

%Vor%

Ich übernehme keine Garantie für den Nutzen oder die Gesundheit des obigen Codes. Tatsächlich garantiere ich, dass es ist verrückt ist, und Sie sollten es vermeiden, es zu verwenden, außer Sie wollen eine Auspeitschung von Ihren Python-Peers.

Dieser Code ähnelt dem Code von Eduffy und John Montgomery, stellt aber sicher, dass "z" wie eine lokale Variable erstellt und ordnungsgemäß wiederhergestellt wird. Beachten Sie beispielsweise, wie "other_recurse" die Bindung sehen kann für 'z' im Rumpf von 'recurse' angegeben.

    
Aaron 26.02.2009, 19:20
quelle
8

Ich weiß nichts über den lokalen Bereich, aber Sie könnten vorübergehend einen alternativen globalen Namensraum bereitstellen. Etwas wie:

%Vor%

Was "Wert von z" drucken soll

    
John Montgomery 26.02.2009 16:23
quelle
7

a) tu es nicht.

b) Ernst, warum würdest du das tun?

c) Sie könnten z als global innerhalb Ihres Decorators deklarieren, also wird z nicht in globals () sein, bis der Decorator zum ersten Mal aufgerufen wurde, also wird die Assert nicht bellen.

d) warum ???

    
hop 26.02.2009 16:26
quelle
2

Ich werde zuerst das "bitte nicht" wiederholen, aber das ist deine Entscheidung. Hier ist eine Lösung für Sie:

%Vor%

Es erfordert z in den formalen Parametern, aber nicht das tatsächliche.

    
eduffy 26.02.2009 19:09
quelle
1

Ich könnte wahrscheinlich einen ähnlichen Effekt durch die Verwendung der Klasseninfrastruktur bekommen, aber ich wollte sehen, ob es mit rohen Funktionen machbar ist.

Nun, Python ist eine objektorientierte Sprache. Du solltest das in einer Klasse machen, meiner Meinung nach. Eine nette Klassenschnittstelle zu erstellen würde Ihr Problem sicherlich vereinfachen. Das ist nicht , für welche Dekoratoren es gemacht wurde.

    
kender 26.02.2009 19:02
quelle
1

Explizit ist besser als implizit.

Ist das gut genug?

%Vor%

(Wenn Sie wirklich böse wollen, scheint die Zuweisung zu f.func_globals Spaß zu machen.)

    
cthulahoops 27.02.2009 00:19
quelle
0

Andere haben ein paar Möglichkeiten gegeben, einen funktionierenden Dekorateur zu machen, viele haben davon abgeraten, weil es so stilistisch anders ist als normales Python-Verhalten, dass es wirklich jeden verwirren wird, der versucht, den Code zu verstehen.

Wenn Sie die Dinge viel neu berechnen müssen, wäre es sinnvoll, sie in einem Objekt zusammenzufassen? Berechne z1 ... zN im Konstruktor, dann können die Funktionen, die diese Werte verwenden, auf die vorberechneten Antworten als Teil der Instanz zugreifen.

    
Mr Fooz 27.02.2009 00:50
quelle

Tags und Links