Frage

Bitte entschuldigen Sie die vage Titel. Wenn jemand einen Vorschlag hat, lassen Sie es mich wissen! Geben Sie bitte auch mit mehr entsprechenden Tags retag!

Das Problem

Ich möchte eine Instanz einer importierten Klasse müssen in der Lage sein, die Dinge in den Rahmen (Globals, Einheimische) des Importeurs zu sehen. Da ich bei der Arbeit hier nicht sicher über den genauen Mechanismus bin, kann ich es viel besser beschreiben mit Schnipsel als Worte.

## File 1
def f1():  print "go f1!"

class C1(object):
    def do_eval(self,x):  # maybe this should be do_evil, given what happens
        print "evaling"
        eval(x)
        eval(x,globals(),locals())

Dann von einer iteractive Sitzung dieses Code ausführen, gibt es viele NameErrors sein

## interactive
class C2(object):
    def do_eval(self,x):  # maybe this should be do_evil, given what happens
        print "evaling"
        eval(x)
        eval(x,globals(),locals())

def f2():
    print "go f2!"

from file1 import C1
import file1

C1().do_eval('file1.f1()')
C1().do_eval('f1()')
C1().do_eval('f2()')

file1.C1().do_eval('file1.f1()')
file1.C1().do_eval('f1()')
file1.C1().do_eval('f2()')

C2().do_eval('f2()')
C2().do_eval('file1.f1()')
C2().do_eval('f1()')

Gibt es ein gemeinsames Idiom / Muster für diese Art von Aufgabe? Bin ich Bellen völlig den falschen Baum?

War es hilfreich?

Lösung

In diesem Beispiel können Sie einfach als Objekte über Funktionen zu den Methoden in C1:

>>> class C1(object):
>>>    def eval(self, x):
>>>        x()
>>>
>>> def f2(): print "go f2"
>>> c = C1()
>>> c.eval(f2)
go f2

In Python können Sie Funktionen und Klassen zu anderen Methoden übergeben und rufen / erstellen sie dort.

Wenn Sie möchten, um tatsächlich ein Code-String auswerten, müssen Sie die Umgebung angeben, wie bereits von Thomas erwähnt.

Ihr Modul von oben, leicht verändert:

## File 1
def f1():  print "go f1!"

class C1(object):
    def do_eval(self, x, e_globals = globals(), e_locals = locals()):
        eval(x, e_globals, e_locals)

Nun, im interaktiven Interpreter:

>>> def f2():
>>>    print "go f2!"
>>> from file1 import *    # 1
>>> C1().do_eval("f2()")   # 2
NameError: name 'f2' is not defined

>>> C1().do_eval("f2()", globals(), locals()) #3
go f2!
>>> C1().do_eval("f1()", globals(), locals()) #4
go f1!

Einige Anmerkungen

  1. Hier legen wir alle Objekte aus file1 in dieses Modul Namensraum
  2. f2 ist nicht im Namensraum von file1, deshalb bekommen wir eine NameError
  3. Nun passieren wir die Umwelt explictly, und der Code ausgewertet werden
  4. f1 ist im Namensraum des Moduls, weil wir es importiert

Bearbeiten :. Hinzugefügt Codebeispiel auf, wie explizit Umgebung passiert für eval

Andere Tipps

Die Funktionen werden immer im Rahmen ausgeführt sie in definiert sind, wie Methoden und Klassenkörper. Sie werden nie in einem anderen Bereich ausgeführt werden. Da Import nur ein weitere Zuweisung ist, und alles, was in Python ist eine Referenz, die Funktionen, Klassen und Module nicht einmal wissen, wo sie importiert werden.

Sie können zwei Dinge tun: explizit die ‚Umwelt‘ übergeben wollen, um sie zu verwenden, oder die Verwendung Stapel hackery ihrer Anrufers Namespace zugreifen. Ersteres wird in beträchtlichem Ausmaß gegenüber letzteren bevorzugt, da es nicht so abhängig von der Implementierung und zerbrechlich wie dieser ist.

Sie können möchten an der string.Template Klasse suchen, die etwas ähnliches zu tun versucht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top