In Python 2, wie kann ich schreiben auf Variablen im übergeordneten Bereich?
Ich habe den folgenden code innerhalb einer Funktion:
stored_blocks = {}
def replace_blocks(m):
block = m.group(0)
block_hash = sha1(block)
stored_blocks[block_hash] = block
return '{{{%s}}}' % block_hash
num_converted = 0
def convert_variables(m):
name = m.group(1)
num_converted += 1
return '<%%= %s %%>' % name
fixed = MATCH_DECLARE_NEW.sub('', template)
fixed = MATCH_PYTHON_BLOCK.sub(replace_blocks, fixed)
fixed = MATCH_FORMAT.sub(convert_variables, fixed)
Hinzufügen von Elementen zu stored_blocks
funktioniert gut, aber ich kann nicht zu einer Erhöhung num_converted
in der zweiten Teilfunktion:
UnboundLocalError: lokale variable 'num_converted' referenced before assignment
Könnte ich global
aber Globale Variablen sind hässlich und ich weiß wirklich nicht brauchen, dass variable global an alle.
So, ich bin gespannt, wie ich schreiben kann, um eine variable in der übergeordneten Funktion scope.
nonlocal num_converted
würde wahrscheinlich den job zu erledigen, aber ich brauche eine Lösung, die funktioniert mit Python 2.x.
- Im Gegensatz zu etwas landläufigen Meinung (Beurteilung durch diese Art der Fragen)
def
ist nicht das einzige Schlüsselwort, definiert eine namespace: es gibt auchclass
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Problem: Dies ist, weil Python die scoping-Regeln sind dement. Die Anwesenheit der
+=
Zuweisungs-operator markiert das Ziel, innum_converted
, als lokal auf dem umschließenden Funktions-scope, und es ist kein Ton Art in Python 2.x, um den Zugriff nur einem scoping-Ebene aus. Nur dieglobal
Stichwort heben können variable Bezüge aus dem aktuellen Bereich, und es bringt Sie direkt an die Spitze.Update: Drehen
num_converted
in a single-element array.+=
Zuweisungs-operator markiert das Ziel, innum_converted
, als lokal auf dem umschließenden Funktions-scope, und es ist kein Ton Art in Python 2.x, um den Zugriff nur einem scoping-Ebene aus. Nur dieglobal
Stichwort heben können variable Bezüge aus dem aktuellen Bereich, und es bringt Sie direkt an die Spitze.global
bedeutet nicht, dass Sie nicht über eine Globale variable.scope = {'num_converted':0} … scope['num_converted'] += 1
.(siehe unten für die bearbeitete Antwort)
Können Sie so etwas wie:
Diese Weise
num_converted
funktioniert wie ein C-wie "static" variable, die convert_variable Methode(bearbeitet)
Diese Weise brauchen Sie nicht initialisiert den Zähler in der main-Prozedur.
convert_variables.num_converted
nachdem definieren der Funktion, aber es sieht seltsam aus, so zu tun.Mithilfe der
global
Schlüsselwort ist in Ordnung. Wenn Sie schreiben:...
num_converted
nicht zu einer "globalen variable" (also nicht sichtbar, in anderen unerwarteten Orten), es bedeutet nur, es kann geändert werden, innerhalbconvert_variables
. Das scheint genau das, was Sie wollen.Um es anders auszudrücken,
num_converted
ist bereits eine Globale variable. Alleglobal num_converted
syntax teilt Python "innerhalb dieser Funktion, nicht die Erstellung einer lokalennum_converted
variable, verwenden Sie stattdessen die vorhandene Globale.global
im 2.x arbeitet ziemlich viel, wienonlocal
hat in 3.x.Was über die Verwendung von Klasse-Instanz zu halten den Staat?
Sie instanziiert eine Klasse, und übergeben Sie die Instanz-Methoden, um subs und solche Funktionen würde einen Verweis auf sich selbst...
Ich habe einige Bemerkungen.
Erste, eine Anwendung für eine solche verschachtelte Funktionen kommt beim Umgang mit raw-Rückrufe, so sind die in Bibliotheken verwendet werden, wie xml.Parser.expat. (Die Bibliothek der Autoren wählten diesen Ansatz, die bedenklich sein könnten, aber ... es gibt Gründe, warum Sie es dennoch.)
Sekunde: innerhalb einer Klasse gibt es viel schönere alternativen zum array (num_converted[0]). Ich vermute, das ist, was Sebastjan Rede.
Es ist immer noch seltsam genug, um Verdienst zu, einen Kommentar im code...
Aber die variable ist zumindest lokal zu der Klasse.
Geändert von: https://stackoverflow.com/a/40690954/819544
Nutzen Sie das
inspect
Modul Zugriff auf die aufrufende Bereich globals dict und schreiben Sie in die. Das bedeutet, dass dieser trick kann auch genutzt werden, um Zugriff auf das aufrufen von Rahmen aus einer geschachtelten Funktion definiert, die in einem importierten submodule.Spielen mit der
scope_level
argument, wie gebraucht. Einstellungscope_level=1
arbeitet für eine definierte Funktion in ein Submodul,scope_level=2
für die innere Funktion definiert einen Dekorateur in einem Submodul, etc.NB: Nur weil du kann dies tun, bedeutet nicht, Sie sollten.