3964 Stimmen

Verwendung globaler Variablen in einer Funktion

Wie kann ich eine globale Variable in einer Funktion erstellen oder verwenden?

Wenn ich in einer Funktion eine globale Variable erstelle, wie kann ich diese globale Variable in einer anderen Funktion verwenden? Muss ich die globale Variable in einer lokalen Variable der Funktion speichern, die ihren Zugriff benötigt?

0 Stimmen

Unabhängig davon, wo Sie "global" vor dem Variablennamen erwähnt haben, kann sie überall wie eine normale lokale Variable verwendet werden, sobald Python sie als mit dem Schlüsselwort "global" gelesen hat. Aber es ist eine sehr schlechte Idee, es sei denn, die Variable ist für das gesamte Projekt gemeinsam. Zum Beispiel: project_name, database_url

5193voto

Paul Stephenson Punkte 63913

Sie können eine globale Variable in anderen Funktionen verwenden, indem Sie sie als global innerhalb jeder Funktion, die ihr einen Wert zuweist:

globvar = 0

def set_globvar_to_one():
    global globvar    # Needed to modify global copy of globvar
    globvar = 1

def print_globvar():
    print(globvar)     # No need for global declaration to read value of globvar

set_globvar_to_one()
print_globvar()       # Prints 1

Da es unklar ist, ob globvar = 1 eine lokale Variable erstellt oder eine globale Variable ändert, erstellt Python standardmäßig eine lokale Variable und lässt Sie explizit das andere Verhalten mit der Option global Stichwort.

Siehe andere Antworten, wenn Sie eine globale Variable modulübergreifend nutzen wollen.

1028 Stimmen

Es ist eine extreme Übertreibung, Globals als "so gefährlich" zu bezeichnen. Globals sind in jeder Sprache, die es je gegeben hat und geben wird, völlig in Ordnung. Sie haben ihren Platz. Was Sie sagen sollten, ist, dass sie Probleme verursachen können, wenn Sie keine Ahnung vom Programmieren haben.

259 Stimmen

Ich denke, sie sind ziemlich gefährlich. Jedoch in Python "globale" Variablen sind eigentlich Modul-Ebene, die eine Menge Probleme löst.

911voto

Jeff Shannon Punkte 9273

Wenn ich Ihre Situation richtig verstehe, ist das, was Sie sehen, das Ergebnis davon, wie Python lokale (Funktion) und globale (Modul) Namensräume behandelt.

Nehmen wir an, Sie haben ein Modul wie dieses:

# sample.py
myGlobal = 5

def func1():
    myGlobal = 42

def func2():
    print myGlobal

func1()
func2()

Man könnte erwarten, dass dies 42 ausgibt, aber stattdessen wird 5 ausgegeben. Wie bereits erwähnt, können Sie durch Hinzufügen eines ' global ' Erklärung an func1() dann func2() wird 42 gedruckt.

def func1():
    global myGlobal
    myGlobal = 42

Was hier vor sich geht, ist, dass Python annimmt, dass jeder Name, der zugewiesen innerhalb einer Funktion ist lokal für diese Funktion, es sei denn, es wird ausdrücklich etwas anderes gesagt. Wenn es nur Lesen von einem Namen ableitet und der Name lokal nicht existiert, wird versucht, den Namen in allen enthaltenen Bereichen (z.B. im globalen Bereich des Moduls) zu suchen.

Wenn Sie dem Namen 42 zuordnen myGlobal Daher erstellt Python eine lokale Variable, die die globale Variable gleichen Namens überschattet. Diese lokale Variable verlässt den Geltungsbereich und ist Müllsammeln cuando func1() zurück; inzwischen, func2() kann nie etwas anderes sehen als den (unveränderten) globalen Namen. Beachten Sie, dass diese Namespace-Entscheidung zur Kompilierzeit geschieht, nicht zur Laufzeit -- wenn Sie den Wert von myGlobal innerhalb func1() bevor Sie es zuweisen, erhalten Sie eine UnboundLocalError weil Python bereits entschieden hat, dass es sich um eine lokale Variable handeln muss, der aber noch kein Wert zugewiesen wurde. Aber durch die Verwendung des ' global Anweisung teilen Sie Python mit, dass es den Namen woanders suchen soll, anstatt ihn lokal zuzuweisen.

(Ich glaube, dass dieses Verhalten größtenteils durch eine Optimierung lokaler Namensräume entstanden ist -- ohne dieses Verhalten müsste Pythons VM jedes Mal, wenn ein neuer Name innerhalb einer Funktion zugewiesen wird, mindestens drei Namenssuchen durchführen (um sicherzustellen, dass der Name nicht bereits auf Modul-/Builtin-Ebene existiert), was eine sehr häufige Operation erheblich verlangsamen würde).

1 Stimmen

Sie haben erwähnt, dass die Namespace-Entscheidung bei Kompilierzeit Ich glaube nicht, dass es wahr ist. Nach dem, was ich gelernt habe, kompiliert Python prüft nur auf Syntaxfehler, nicht auf Namensfehler Versuchen Sie dieses Beispiel def A(): x+=1 wenn Sie es nicht ausführen, wird es nicht zu UnboundLocalError führen Bitte überprüfen Sie das, danke.

1 Stimmen

Es ist üblich, einen Großbuchstaben für globale Variablen zu verwenden wie MyGlobal = 5

5 Stimmen

@watashiSHUN: Die Namespace-Entscheidung tut zur Kompilierzeit geschehen. Die Entscheidung, dass x lokal ist, unterscheidet sich von der Überprüfung zur Laufzeit, ob der lokale Name an einen Wert gebunden wurde, bevor er das erste Mal verwendet wird.

279voto

gimel Punkte 78080

Vielleicht möchten Sie sich mit dem Konzept der Namensräume . In Python ist die Modul ist der natürliche Ort für weltweit Daten:

Jedes Modul hat seine eigene private Symboltabelle, die als globale Symboltabelle von allen im Modul definierten Funktionen verwendet wird. Auf diese Weise kann der Autor eines Moduls globale Variablen im Modul verwenden, ohne sich Gedanken über versehentliche Konflikte mit den globalen Variablen eines Benutzers zu machen. Andererseits können Sie, wenn Sie wissen, was Sie tun, die globalen Variablen eines Moduls mit der gleichen Notation ansprechen, die Sie auch für die Funktionen des Moduls verwenden, modname.itemname .

Eine spezielle Verwendung von global-in-a-module wird hier beschrieben - Wie kann ich globale Variablen modulübergreifend nutzen? und der Vollständigkeit halber wird der Inhalt hier wiedergegeben:

Der klassische Weg, um Informationen zwischen Modulen innerhalb eines einzelnen Programms auszutauschen, ist die Erstellung eines speziellen Konfigurationsmoduls (oft als Konfiguration o cfg ). Importieren Sie das Konfigurationsmodul einfach in alle Module Ihrer Anwendung; das Modul ist dann als globaler Name verfügbar. Da es nur eine Instanz jedes Moduls gibt, werden alle Änderungen am Modulobjekt überall übernommen. Zum Beispiel:

Datei: config.py

x = 0   # Default value of the 'x' configuration setting

Datei: mod.py

import config
config.x = 1

Datei: main.py

import config
import mod
print config.x

1 Stimmen

Aus einem Grund, der mir nicht gefällt config.x kann ich sie loswerden? Ich kam mit x = lambda: config.x und dann habe ich die neu Wert in x() . aus irgendeinem Grund, wenn man a = config.x ist für mich nicht hilfreich.

6 Stimmen

@vladosaurus tut from config import x das lösen?

123voto

Python verwendet eine einfache Heuristik, um zu entscheiden, aus welchem Bereich eine Variable geladen werden soll, zwischen lokal und global. Wenn ein Variablenname auf der linken Seite einer Zuweisung erscheint, aber nicht als global deklariert ist, wird angenommen, dass er lokal ist. Erscheint er nicht auf der linken Seite einer Zuweisung, wird er als global angenommen.

>>> import dis
>>> def foo():
...     global bar
...     baz = 5
...     print bar
...     print baz
...     print quux
... 
>>> dis.disassemble(foo.func_code)
  3           0 LOAD_CONST               1 (5)
              3 STORE_FAST               0 (baz)

  4           6 LOAD_GLOBAL              0 (bar)
              9 PRINT_ITEM          
             10 PRINT_NEWLINE       

  5          11 LOAD_FAST                0 (baz)
             14 PRINT_ITEM          
             15 PRINT_NEWLINE       

  6          16 LOAD_GLOBAL              1 (quux)
             19 PRINT_ITEM          
             20 PRINT_NEWLINE       
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE        
>>> 

Sehen Sie, wie baz, das auf der linken Seite eines Auftrags in foo() ist die einzige LOAD_FAST variabel.

15 Stimmen

Die Heuristik sucht nach Bindearbeiten . Die Zuweisung ist eine solche Operation, der Import eine andere. Aber das Ziel einer for Schleife und der Name nach as en with y except Aussagen sind auch an diese gebunden.

0 Stimmen

@MartijnPieters Für den Namen nach as in einem except Klausel war dies für mich nicht offensichtlich. Aber sie wird automatisch gelöscht, um Speicherplatz zu sparen.

2 Stimmen

@Robert: nicht um Speicher zu sparen, sondern um zu vermeiden, dass eine zirkuläre Referenz entsteht, die zu Speicherlecks führen kann. Das liegt daran, dass eine Ausnahme einen Traceback referenziert, und der Traceback referenziert jeden lokalen und globalen Namespace entlang des gesamten Aufrufstapels, einschließlich des as ... Ziel im Exception-Handler.

78voto

J S Punkte 1007

Wenn Sie sich in einer Funktion auf eine globale Variable beziehen wollen, können Sie die weltweit Schlüsselwort, um zu deklarieren, welche Variablen global sind. Sie müssen es nicht in allen Fällen verwenden (wie jemand hier fälschlicherweise behauptet) - wenn der Name, auf den in einem Ausdruck verwiesen wird, nicht im lokalen Bereich oder in den Bereichen der Funktionen, in denen diese Funktion definiert ist, gefunden werden kann, wird er unter den globalen Variablen gesucht.

Wenn Sie jedoch eine neue Variable zuweisen, die in der Funktion nicht als global deklariert ist, wird sie implizit als lokal deklariert und kann jede bestehende globale Variable mit demselben Namen überschatten.

Außerdem sind globale Variablen nützlich, im Gegensatz zu einigen OOP-Eiferern, die das Gegenteil behaupten - vor allem bei kleineren Skripten, wo OOP ein Overkill ist.

0 Stimmen

Absolut, was die Eiferer betrifft. Die meisten Python-Benutzer verwenden es für die Skripterstellung und erstellen kleine Funktionen, um kleine Teile des Codes zu trennen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X