Frage

locals ist eine integrierte Funktion, die ein Wörterbuch der lokalen Werte zurückgibt. Die Dokumentation sagt:

  

Warnung

     

Der Inhalt dieses Wörterbuch sollte   , Nicht modifiziert werden, Änderungen können nicht   Auswirkungen auf die Werte von lokalen Variablen   vom Interpreter verwendet.

Leider exec hat das gleiche Problem in Python 3.0. Gibt es eine Möglichkeit Runde das?

Use Case

Bedenken Sie:

@depends("a", "b", "c", "d", "e", "f")
def test():
    put_into_locals(test.dependencies)

hängt speichert die Saiten in ihre Argumente in einer Liste test.dependences zur Verfügung gestellt. Diese Strings sind die Schlüssel in einem Wörterbuch d. Ich möchte in der Lage sein können put_into_locals schreiben, so dass wir die Werte aus d ziehen konnte und sie in die Einheimischen setzen. Ist das möglich?

War es hilfreich?

Lösung

I exec nur getestet und es funktioniert in Python 2.6.2

>>> def test():
...     exec "a = 5"
...     print a
...
>>> test()
5

Wenn Sie Python 3.x verwenden, ist es nicht mehr arbeiten, weil Einheimische als Array zur Laufzeit optimiert werden, anstatt ein Wörterbuch zu verwenden.

Wenn Python die „exec-Anweisung“ erkennt, wird es Python zwingt lokale Speicherung von Array-Wörterbuch zu wechseln. Da jedoch „exec“ eine Funktion in Python 3.x ist, kann der Compiler diese Unterscheidung nicht machen, da der Benutzer so etwas wie „exec = 123“ getan haben könnte.

http://bugs.python.org/issue4831

  

die Einheimischen einer Funktion ändern auf   die Fliege ist nicht möglich, ohne   mehrere Konsequenzen: in der Regel,   Funktion Einheimischen sind nicht in einer gespeicherten   Wörterbuch, aber ein Array, das   Indizes werden zum Zeitpunkt der Kompilierung bestimmt   von den bekannten Schauplätzen. Dies kollidiert   zumindest mit neuen Einheimischen hinzugefügt von   exec. Die alte exec   umgangen dies, weil die   Compiler wusste, dass, wenn eine exec ohne   Globals / Einheimische args ereignete sich in einem   Funktion, wäre das Namespace   „Nicht optimiert“, das heißt nicht unter Verwendung des   Einheimische Array. Da exec () ist jetzt ein   normale Funktion, funktioniert der Compiler nicht   wissen, was „exec“ gebunden sein kann, und   kann daher nicht behandelt, ist speziell.

Andere Tipps

Die lokalen Variablen werden durch Zuweisungen geändert.

Wenn Sie Dictionary-Schlüssel haben, die Saiten sind, bitte sie lokale Variablen nicht auch machen -. Nur sie als Dictionary-Schlüssel verwenden

Wenn Sie unbedingt muss haben lokale Variablen tun.

def aFunction( a, b, c, d, e, f ):
    # use a, b, c, d, e and f as local variables

aFunction( **someDictWithKeys_a_b_c_d_e_f )

Das wird einige lokalen Variablen aus dem Wörterbuch füllen, ohne magisch etwas zu tun.

Dies ist nicht möglich. Ich denke, das später für Performance-Optimierungen zu ermöglichen ist. Python-Bytecode verweist Einheimischen durch den Index, nicht namentlich; wenn Einheimische () war erforderlich, um beschreibbar zu sein, könnte es Dolmetscher verhindern, dass einige Optimierungen implementieren oder sie erschweren.

Ich bin ziemlich sicher, du wirst keinen Kern-API finden, die Sie so garantiert können Einheimischer bearbeiten, denn wenn die API es tun könnte, Einheimische () würde diese Einschränkung nicht hat entweder.

Vergessen Sie nicht, dass alle Einheimischen zur Compile-Zeit vorhanden sein muss; wenn Sie einen Namen verweisen, die nicht zu einem lokalen zur Compile-Zeit gebunden ist, nimmt der Compiler es eine global ist. Sie können nicht „schaffen“ Einheimischen nach der Kompilierung.

Siehe

Ich würde speichern Sie es in einer Variablen:

refs    = locals()
def set_pets():
    global refs
    animals = ('dog', 'cat', 'fish', 'fox', 'monkey')
    for i in range(len(animals)):
        refs['pet_0%s' % i] = animals[i]

set_pets()
refs['pet_05']='bird'
print(pet_00, pet_02, pet_04, pet_01, pet_03, pet_05 )
>> dog fish monkey cat fox bird

Und wenn Sie möchten, dass Ihre dict testen, bevor es in den Einheimischen setzen ():

def set_pets():
    global refs
    sandbox = {}
    animals = ('dog', 'cat', 'fish', 'fox', 'monkey')
    for i in range(len(animals)):
        sandbox['pet_0%s' % i] = animals[i]
    # Test sandboxed dict here
    refs.update( sandbox )

Python 3.6.1 auf MacOS Sierra

Ich bin mir nicht sicher, ob es die gleichen Einschränkungen unterworfen ist, aber Sie können einen direkten Verweis auf den aktuellen Rahmen erhalten (und von dort die lokalen Variablen Wörterbuch) durch das Modul überprüfen:

>>> import inspect
>>> inspect.currentframe().f_locals['foo'] = 'bar'
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'foo', 'inspect']
>>> foo
'bar'
scroll top