Den Block der Befehle, die in der mit Anweisung ausgeführt werden sollen

Beim Lesen der Spezifikationen für die with Aussage ( Link ), habe ich einige Dinge, die ich gerne mit spielen würde. Dies ist nicht für irgendeinen Produktionscode oder irgendetwas, ich bin nur erforschen, also bitte nicht zu hart sein, wenn dies eine schlechte Idee ist.

Was ich gerne machen möchte, packt das Stück namens "BLOCK" in den verknüpften Dokumenten oben, und tatsächlich bastelt es mit ihm innerhalb des Aufrufs zu __enter__ . (Siehe das verknüpfte doc, kurz nach Beginn des Motivations- und Zusammenfassungsbereichs).

Die Idee ist, meine eigene Art von on-the-fly lokalen Namespace zu schaffen. Etwas wie das:

 with MyNameSpace(some_object): print a #Should print some_object.a x = 4 #Should set some_object.x=4 

Grundsätzlich möchte ich, dass die Aussagen innerhalb des Blocks den lokalen Variablen und Zuordnungskonventionen von some_object .

In meinem konkreten Fall könnte some_object ein spezielles Daten-Array sein, das meine eigenen some_object Operationen hat oder so. In diesem Fall sagen wir etwas wie x = y + 5 if y > 4 else y - 2 könnte einige fancy NumPy vektorisierte Operation unter der Haube, aber ich brauche nicht explizit anrufen some_object 's Schnittstelle zu diesen Methoden. Im Namespace sollten die Ausdrücke "nur funktionieren" (wie ich sie definiere, dass sie in der MyNameSpace Klasse abgeleitet werden sollen.

Meine erste Idee ist, irgendwie den Prozess zu unterbrechen und den Code zu bekommen, der in den try Block geht. Dann interpretiere diesen Code, wenn __enter__ angerufen wird, und ersetze den Code im try Block mit etwas anderem (vielleicht pass wenn das funktionieren würde, aber evtl. etwas, das some_object wieder in den ursprünglichen Variablenbereich mit seinen neuen geänderten Variablen wiederherstellt).

Ein einfacher Testfall wäre so:

 my_dict = {'a':3, 'b':2} with MyNameSpace(my_dict): print a # Should print 3 x = 5 # When the block finishes, my_dict['x'] should now be 5 

Ich bin interessiert, wenn diese Idee schon irgendwo existiert.

Ich bin mir bewusst von Best Practices Dinge für die Zuweisung von Variablen. Dies ist ein Haustier-Projekt, also bitte annehmen, dass, nur um dieser Idee willen, können wir ignorieren Best Practices. Auch wenn du es nicht möchtest, Variablen auf diese Weise zuzuordnen, könnte es in meinem aktuellen Projekt nützlich sein.

Bearbeiten

Um die Art von kniffligen Sachen zu klären, die ich vielleicht tun möchte, und um die Antwort unten zu behaupten, dass es nicht getan werden kann, betrachten Sie die Beispieldatei testLocals.py unten:

 my_dict = {'a':1, 'b':2} m = locals() print m["my_dict"]['a'] m["my_dict"]['c'] = 3 print my_dict class some_other_scope(object): def __init__(self, some_scope): x = 5 g = locals() some_scope.update(g) some_scope["my_dict"]["d"] = 4 sos = some_other_scope(m) print my_dict print x 

Was folgendes gibt, wenn ich es nicht interaktiv betreibe:

 ely@AMDESK:~/Desktop/Programming/Python$ python testLocals.py 1 {'a': 1, 'c': 3, 'b': 2} {'a': 1, 'c': 3, 'b': 2, 'd': 4} 5 

2 Solutions collect form web for “Den Block der Befehle, die in der mit Anweisung ausgeführt werden sollen”

Versuche dies.

 import sys class MyNameSpace(object): def __init__(self,ns): self.ns = ns def __enter__(self): globals().update(self.ns) def __exit__(self, exc_type,exc_value,traceback): self.ns.update(sys._getframe(1).f_locals) my_dict = {'a':3, 'b':2} with MyNameSpace(my_dict) as ns: print(a) # Should print 3 x = 5 # When the block finishes, my_dict['x'] should now be 5 print(my_dict['x']) 

Hier ist etwas Ähnliches, das ich vor ein paar Monaten versuchte:

 import sys import inspect import collections iscallable = lambda x: isinstance(x, collections.Callable) class Namespace(object): def __enter__(self): """store the pre-contextmanager scope""" f = inspect.currentframe(1) self.scope_before = dict(f.f_locals) return self def __exit__(self, exc_type, exc_value, traceback): """determine the locally declared objects""" f = inspect.currentframe(1) scope_after = dict(f.f_locals) scope_context = set(scope_after) - set(self.scope_before) # capture the local scope, ignoring the context manager itself self.locals = dict( (k, scope_after[k]) for k in scope_context if not isinstance(scope_after[k], self.__class__) ) for name in self.locals: obj = scope_after[name] if iscallable(obj): # closure around the func_code with the appropriate locals _wrapper = type(lambda: 0)(obj.func_code, self.locals) self.__dict__[name] = _wrapper # update locals so the calling functions refer to the wrappers too self.locals[name] = _wrapper else: self.__dict__[name] = obj # remove from module scope del sys.modules[__name__].__dict__[name] return self with Namespace() as Spam: x = 1 def ham(a): return x + a def cheese(a): return ham(a) * 10 

Es wird geprüft, um die Einheimischen während des Kontextmanagers zu ändern und dann die ursprünglichen Werte wieder zuzuordnen, wenn sie fertig sind.

Es ist nicht perfekt – ich kann mich nicht erinnern wo es Probleme trifft, aber ich bin sicher, dass es tut – aber es könnte Ihnen helfen, loszulegen.

  • Python: Wie erfasse ich eine Variable, die in einem nicht globalen Ahnenumfang angegeben ist?
  • Warum ist der Ort zum Zeitpunkt der Kompilierung bestimmt?
  • Wie man globale Variablen unter verschiedenen Modulen in Python hat
  • "Lokale Variable referenziert vor Zuordnung" - nur Funktionen?
  • UnboundLocalError bei der Manipulation von Variablen ergibt inkonsistentes Verhalten
  • Warum verschachtelte Funktionen auf Variablen von äußeren Funktionen zugreifen können, aber sie nicht ändern dürfen [duplizieren]
  • Blockieren Sie den Bereich in Python
  • Globals und Einheimische in python exec ()
  • Scoping in Python 'für' Schleifen
  • Python-Funktion Anrufe sind Blutungen Umfang, stateful, nicht zu initialisieren Parameter?
  • Funktion Ortsname Bindung aus einem äußeren Bereich
  • Python ist die beste Programmiersprache der Welt.