webentwicklung-frage-antwort-db.com.de

Grund für globals () in Python?

Was ist der Grund dafür, dass globals () in Python funktioniert? Es gibt nur Wörterbuch globaler Variablen zurück, die bereits global sind, also können sie überall verwendet werden ...

def F():
    global x
    x = 1

def G():
    print(globals()["x"]) #will return value of global 'x', which is 1

def H():
    print(x) #will also return value of global 'x', which, also, is 1

F()
G()
H()

Ich kann den Punkt hier nicht wirklich sehen. Ich brauchte es nur Zeit, wenn ich lokale und globale Variablen mit demselben Namen für beide hätte

def F():
    global x
    x = 1

def G():
    x = 5
    print(x) #5
    print(globals()["x"]) #1

F()
G()

Sie sollten jedoch niemals auf das Problem stoßen, dass zwei Variablen denselben Namen haben und beide innerhalb desselben Bereichs verwendet werden müssen.

58
user1632861

Python bietet dem Programmierer eine Vielzahl von Tools für die Introspektion der laufenden Umgebung. globals() ist nur eine davon und kann in einer Debugging-Sitzung sehr nützlich sein, um zu sehen, welche Objekte der globale Gültigkeitsbereich tatsächlich enthält.

Ich bin sicher, der Grund dafür ist derselbe wie bei der Verwendung von locals(), um die in einer Funktion definierten Variablen anzuzeigen, oder mit dir, um den Inhalt eines Moduls oder die Attribute eines Objekts anzuzeigen.

Ich komme aus einem C++ - Hintergrund und kann verstehen, dass diese Dinge unnötig erscheinen. In einer statisch verknüpften, statisch typisierten Umgebung wären sie das absolut. In diesem Fall ist zum Zeitpunkt der Kompilierung genau bekannt, welche Variablen global sind und welche Member ein Objekt haben wird, und sogar, welche Namen von einer anderen Kompilierungseinheit exportiert werden.

In einer dynamischen Sprache sind diese Dinge jedoch nicht festgelegt. Sie können sich je nach Art des Codes oder sogar während der Laufzeit ändern. Zumindest aus diesem Grund kann der Zugriff auf diese Informationen in einem Debugger von unschätzbarem Wert sein.

77
Ian Clelland

Dies ist auch nützlich, wenn Sie eine Funktion mit dem String-Namen der Funktion aufrufen müssen. Zum Beispiel:

def foo():
    pass

function_name_as_string = 'foo'

globals()[function_name_as_string]() # foo(). 
34
Alex Soroka

Sie können das Ergebnis von globals() und locals() an die Befehle eval, execfile und __import__ übergeben. Dadurch wird eine eingeschränkte Umgebung geschaffen, in der die Befehle ausgeführt werden können. 

Daher sind diese Funktionen vorhanden, um andere Funktionen zu unterstützen, die davon profitieren, dass ihnen eine Umgebung gegeben wird, die möglicherweise vom aktuellen Kontext abweicht. Sie können beispielsweise globals() aufrufen und dann einige Variablen entfernen oder hinzufügen, bevor Sie eine dieser Funktionen aufrufen. 

8
Bryan Oakley

globals() ist nützlich für eval() - Wenn Sie Code auswerten möchten, der sich auf Variablen im Gültigkeitsbereich bezieht, sind diese Variablen entweder global oder lokal.


Um ein wenig zu erweitern, interpretiert die eingebaute Funktion eval() eine Zeichenfolge aus Python-Code, die ihr übergeben wurde. Die Signatur lautet: eval(codeString, globals, locals), und Sie würden es so verwenden:

def foo():
    x = 2
    y = eval("x + 1", globals(), locals())
    print("y=" + y) # should be 3

Dies funktioniert, weil der Interpreter den Wert von x vom locals()-Dikt der Variablen erhält. Sie können natürlich Ihr eigenes Diktat von Variablen zur Auswertung angeben.

6
Richard Close

Es kann in 'deklarativem Python' nützlich sein. Im Folgenden sind FooDef und BarDef Klassen, mit denen eine Reihe von Datenstrukturen definiert werden, die dann von einem Paket als Eingabe oder als Konfiguration verwendet werden. Dies gibt Ihnen viel Flexibilität bei der Eingabe und Sie müssen keinen Parser schreiben.

# FooDef, BarDef are classes

Foo_one = FooDef("This one", opt1 = False, valence = 3 )
Foo_two = FooDef("The other one", valence = 6, parent = Foo_one )

namelist = []
for i in range(6):
    namelist.append("nm%03d"%i)

Foo_other = FooDef("a third one", string_list = namelist )

Bar_thing = BarDef( (Foo_one, Foo_two), method = 'depth-first')

Beachten Sie, dass diese Konfigurationsdatei mithilfe einer Schleife eine Liste von Namen erstellt, die Teil der Konfiguration von Foo_other sind. Diese Konfigurationssprache enthält daher einen sehr leistungsfähigen "Präprozessor" mit einer verfügbaren Laufzeitbibliothek. Wenn Sie beispielsweise ein komplexes Protokoll suchen oder Objekte aus einer Zip-Datei extrahieren und diese von base64 decodieren möchten, wird dies im Rahmen der Erstellung Ihrer Konfiguration (dieser Ansatz wird natürlich nicht empfohlen, wenn die Eingabe von einer nicht vertrauenswürdige Quelle ...)

Das Paket liest die Konfiguration wie folgt:

conf_globals = {}  # make a namespace
# Give the config file the classes it needs
conf_globals['FooDef']= mypkgconfig.FooDef  # both of these are based ...
conf_globals['BarDef']= mypkgconfig.BarDef  # ... on .DefBase

fname = "user.conf"
try:
    exec open(fname) in conf_globals
except Exception:
    ...as needed...
# now find all the definitions in there
# (I'm assuming the names they are defined with are
# significant to interpreting the data; so they
# are stored under those keys here).

defs = {}
for nm,val in conf_globals.items():
    if isinstance(val,mypkgconfig.DefBase):
        defs[nm] = val

Um auf den Punkt zu kommen, ist globals() nützlich, wenn Sie ein solches Paket verwenden, wenn Sie eine Reihe von Definitionen prozessual definieren möchten:

for idx in range(20):
    varname = "Foo_%02d" % i
    globals()[varname]= FooDef("one of several", id_code = i+1, scale_ratio = 2**i)

Dies entspricht dem Ausschreiben

Foo_00 = FooDef("one of several", id_code = 1, scale_ratio=1)
Foo_01 = FooDef("one of several", id_code = 2, scale_ratio=2)
Foo_02 = FooDef("one of several", id_code = 3, scale_ratio=4)
... 17 more ...

Ein Beispiel für ein Paket, das seine Eingabe durch Sammeln einer Reihe von Definitionen aus einem Python-Modul erhält, ist PLY (Python-Lex-yacc) http://www.dabeaz.com/ply/ - in diesem Fall das Objekte sind meistens Funktionsobjekte, aber auch Metadaten der Funktionsobjekte (deren Namen, Docstrings und die Reihenfolge der Definition) sind Bestandteil der Eingabe. Es ist kein gutes Beispiel für die Verwendung von globals(). Es wird auch von der 'Konfiguration' importiert - letzteres ist ein normales Python-Skript - und nicht umgekehrt.

Ich habe 'deklarativen Python' für ein paar Projekte verwendet, an denen ich gearbeitet habe, und hatte Gelegenheit, globals() zu verwenden, wenn Sie Konfigurationen für diese Projekte schreiben. Man könnte durchaus argumentieren, dass dies auf eine Schwachstelle in der Konfiguration der Konfigurationssprache zurückzuführen ist. Die Verwendung von globals() auf diese Weise führt nicht zu sehr klaren Ergebnissen. Nur Ergebnisse, die leichter zu warten sind, als ein Dutzend nahezu identischer Aussagen auszusprechen.

Sie können es auch verwenden, um Variablen innerhalb der Konfigurationsdatei nach ihrem Namen Bedeutung zu verleihen:

# All variables above here starting with Foo_k_ are collected
# in Bar_klist
#
foo_k = [ v for k,v in globals().items() if k.startswith('Foo_k_')]
Bar_klist  = BarDef( foo_k , method = "kset")

Diese Methode könnte für das any - Python-Modul nützlich sein, das eine Vielzahl von Tabellen und Strukturen definiert, um das Hinzufügen von Elementen zu den Daten zu erleichtern, ohne dass die Referenzen ebenfalls beibehalten werden müssen.

0
greggo

Es kann auch verwendet werden, um eine Instanz der Klasse 'Klassenname' aus einer Zeichenfolge abzurufen:

class C:
    def __init__(self, x):
        self.x = x
        print('Added new instance, x:', self.x)


def call(str):
    obj = globals()[str](4)
    return obj

c = call('C')
print(c.x)
0
Bart