Verwendung des Schlüsselworts "global" in Python


285

Beim Lesen der Dokumentation verstehe ich, dass Python einen separaten Namespace für Funktionen hat. Wenn ich in dieser Funktion eine globale Variable verwenden möchte, muss ich diese verwenden global.

Ich benutze Python 2.7 und habe diesen kleinen Test ausprobiert

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

Es scheint, dass die Dinge auch ohne gut funktionieren global. Ich konnte problemlos auf globale Variablen zugreifen.

Vermisse ich etwas Folgendes stammt aus der Python-Dokumentation:

In einer globalen Anweisung aufgeführte Namen dürfen nicht als formale Parameter oder in einem for-Regelkreisziel, einer Klassendefinition, einer Funktionsdefinition oder einer Importanweisung definiert werden.

Während formale Parameter und Klassendefinition für mich sinnvoll sind, kann ich die Einschränkung für die Ziel- und Funktionsdefinition der Schleifensteuerung nicht verstehen.


1
Ich denke, Sie sind verwirrt mit PHP, das die Verwendung des globalen Schlüsselworts erfordert - die Python-Dokumente bestätigen dies - im Grunde genommen, wenn es nicht im lokalen Kontext definiert ist, wird es als global behandelt
tobyodavies

11
Seien Sie vorsichtig mit Ihrem Wortlaut: Python hat keinen separaten Namespace für Funktionen (das würde bedeuten, dass Sie ihn haben könnten def foo(): ...und foo = ...gleichzeitig). Es wird für jeden Funktionsaufruf ein neuer Bereich erstellt. (Aber wie unterscheidet sich dies von etwa jeder anderen

Antworten:


366

Das Schlüsselwort globalist nur nützlich, um globale Variablen in einem lokalen Kontext zu ändern oder zu erstellen, obwohl das Erstellen globaler Variablen selten als gute Lösung angesehen wird.

def bob():
    me = "locally defined"    # Defined only in local context
    print(me)

bob()
print(me)     # Asking for a global variable

Das Obige gibt Ihnen:

locally defined
Traceback (most recent call last):
  File "file.py", line 9, in <module>
    print(me)
NameError: name 'me' is not defined

Wenn Sie die globalAnweisung verwenden, wird die Variable "außerhalb" des Funktionsumfangs verfügbar und wird effektiv zu einer globalen Variablen.

def bob():
    global me
    me = "locally defined"   # Defined locally but declared as global
    print(me)

bob()
print(me)     # Asking for a global variable

Der obige Code gibt Ihnen also:

locally defined
locally defined

Aufgrund der Natur von Python können Sie außerdem globalFunktionen, Klassen oder andere Objekte in einem lokalen Kontext deklarieren. Obwohl ich davon abraten würde, da es Albträume verursacht, wenn etwas schief geht oder debuggt werden muss.


59
"global" scheint sich in diesem Zusammenhang von anderen Sprachen zu unterscheiden, die als "global" gelten. In Python befindet sich eine "globale" Referenz immer noch in den Grenzen des Moduls und müsste von außerhalb dieses Moduls als "module.global_var" und nicht wie erwartet als "global_var" referenziert werden.
Saft

17
@juice - In Python gibt es kein Absolut, das globalsautomatisch in allen Namespaces definiert wird (zum Glück). Wie Sie richtig ausgeführt haben, ist ein Global an einen Namespace innerhalb eines Moduls gebunden, kann jedoch als from module import variableoder in ein anderes Modul importiert werden import module.variable. Im ersten Fall würde der Import die Variable als zugänglich machen, variableohne dass eine Referenz erforderlich wäre module.. Ob es im Umfang des Moduls als global betrachtet wird, hängt davon ab, wo es importiert wird. Siehe auch nonlocalals neues
bereichsbezogenes

3
Können Sie erklären, warum globale Variablen keine gute Lösung sind? Ich höre das oft, aber in meinem aktuellen Projekt scheinen sie genau das zu tun, was ich von ihnen brauche. Gibt es etwas Unheimlicheres, an das ich nicht gedacht habe?
Robin Newhouse

5
@RobinNewhouse Es gibt einige Fragen zu SO, die bereits dieses Thema und andere Nicht-SO- Artikel abdecken .
Unode

213

Während Sie ohne das globalSchlüsselwort auf globale Variablen zugreifen können , müssen Sie das Schlüsselwort verwenden, wenn Sie sie ändern möchten global. Zum Beispiel:

foo = 1
def test():
    foo = 2 # new local foo

def blub():
    global foo
    foo = 3 # changes the value of the global foo

In Ihrem Fall greifen Sie nur auf die Liste zu sub.


3
Mit einer Einschränkung: foo = 3Ohne globale Werke, aber foo wird lokal im blubFunktionsumfang neu definiert und ändert die ursprüngliche foo-Variable nicht. Das war ziemlich verwirrend für mich.
Chhantyal

1
@chhantyal Wenn Sie mit Werken meinen, dass es keinen Fehler auslöst, sind Sie richtig, aber im Kontext von Ivo Wetzel würde es nicht wie beabsichtigt funktionieren. Es gibt Verwendungsmöglichkeiten für ein solches Verhalten, aber es ist oft nicht das, was der Programmierer will.
Demokratist

77

Dies ist der Unterschied zwischen dem Zugriff auf den Namen und dem Binden innerhalb eines Bereichs.

Wenn Sie nur nach einer Variablen suchen, um ihren Wert zu lesen, haben Sie Zugriff auf den globalen und den lokalen Bereich.

Wenn Sie jedoch einer Variablen zuweisen, deren Name nicht im lokalen Bereich liegt, binden Sie diesen Namen in diesen Bereich (und wenn dieser Name auch als globaler Name vorhanden ist, wird er ausgeblendet).

Wenn Sie dem globalen Namen zuweisen möchten, müssen Sie den Parser anweisen, den globalen Namen zu verwenden, anstatt einen neuen lokalen Namen zu binden. Dies ist das Schlüsselwort 'global'.

Durch das Binden an einer beliebigen Stelle innerhalb eines Blocks wird der Name überall in diesem Block gebunden, was einige seltsam aussehende Konsequenzen haben kann (z. B. UnboundLocalError, das plötzlich in zuvor funktionierendem Code erscheint).

>>> a = 1
>>> def p():
    print(a) # accessing global scope, no binding going on
>>> def q():
    a = 3 # binding a name in local scope - hiding global
    print(a)
>>> def r():
    print(a) # fail - a is bound to local scope, but not assigned yet
    a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    r()
  File "<pyshell#32>", line 2, in r
    print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>> 

Sehr eingängig, kaum zu glauben, dass dies ein gültiger Python-Code ist
PlsWork

52

Die anderen Antworten beantworten Ihre Frage. Eine weitere wichtige Information über Namen in Python ist, dass sie je nach Gültigkeitsbereich entweder lokal oder global sind.

Betrachten Sie dies zum Beispiel:

value = 42

def doit():
    print value
    value = 0

doit()
print value

Sie können wahrscheinlich davon ausgehen, dass die value = 0Anweisung einer lokalen Variablen zugewiesen wird und den Wert derselben Variablen, die außerhalb der doit()Funktion deklariert wurde, nicht beeinflusst . Sie werden möglicherweise mehr überrascht sein, wenn Sie feststellen, dass der obige Code nicht ausgeführt wird. Die Anweisung print valueinnerhalb der Funktion erzeugt eineUnboundLocalError.

Der Grund dafür ist, dass Python bemerkt hat, dass Sie an anderer Stelle in der Funktion den Namen zuweisen value, und auch valuenirgends deklariert wird global. Das macht es zu einer lokalen Variablen. Wenn Sie jedoch versuchen, es zu drucken, wurde der lokale Name noch nicht definiert. Python greift in diesem Fall nicht wie bei einigen anderen Sprachen auf die Suche nach dem Namen als globale Variable zurück. Grundsätzlich können Sie nicht auf eine globale Variable zugreifen, wenn Sie irgendwo in der Funktion eine lokale Variable mit demselben Namen definiert haben .


1
Vielen Dank für den Hinweis. Solange Ihr lokaler Bereich keinem Namen zugeordnet ist, der außerhalb des Bereichs existiert, verwenden Referenzen im lokalen Bereich den externen Namen. Wenn Sie jedoch irgendwo in Ihrer Funktion diesem Namen zuweisen, sehen Verweise in diesem lokalen Bereich, noch vor der lokalen Zuweisung, nicht nach außen.
Dmitry Minkovsky

1
Genau, du hast es verstanden. global(oder nonlocalin Python 3.x) überschreibt dieses Verhalten und ermöglicht es Ihnen, den externen Namen neu zuzuweisen.
Kindall

2
In anderen Sprachen scheint dies als "Heben" bezeichnet zu werden, wie zum Beispiel: github.com/shichuan/javascript-patterns/blob/master/…
Dmitry

Um noch schlimmer zu machen, deklarierte Variablen mit der neueren JavaScript - Schlüsselwort letist nicht gehisst.
Kindall

Ist es schneller, auf eine mit deklarierte globale Variable zuzugreifen, globaloder spielt es keine Rolle?
Mato

14

Der Zugriff auf einen Namen und die Zuweisung eines Namens sind unterschiedlich. In Ihrem Fall greifen Sie nur auf einen Namen zu.

Wenn Sie einer Variablen innerhalb einer Funktion zuweisen, wird angenommen, dass diese Variable lokal ist, es sei denn, Sie deklarieren sie als global. In Ermangelung dessen wird angenommen, dass es global ist.

>>> x = 1         # global 
>>> def foo():
        print x       # accessing it, it is global

>>> foo()
1
>>> def foo():   
        x = 2        # local x
        print x 

>>> x            # global x
1
>>> foo()        # prints local x
2

7
  • Sie können ohne Schlüsselwort auf globale Schlüsselwörter zugreifen global
  • Um sie ändern zu können, müssen Sie explizit angeben, dass das Schlüsselwort global ist. Andernfalls wird das Schlüsselwort im lokalen Bereich deklariert.

Beispiel:

words = [...] 

def contains (word): 
    global words             # <- not really needed
    return (word in words) 

def add (word): 
    global words             # must specify that we're working with a global keyword
    if word not in words: 
        words += [word]

2

Jede außerhalb einer Funktion deklarierte Variable wird als global angenommen. Nur wenn Sie sie innerhalb von Funktionen deklarieren (außer Konstruktoren), müssen Sie angeben, dass die Variable global ist.


1

Dies wird in den Python-FAQ gut erklärt

Was sind die Regeln für lokale und globale Variablen in Python?

In Python sind Variablen, auf die nur innerhalb einer Funktion verwiesen wird, implizit global. Wenn einer Variablen irgendwo im Funktionskörper ein Wert zugewiesen wird, wird davon ausgegangen, dass es sich um einen lokalen Wert handelt, sofern dies nicht ausdrücklich als global deklariert wird.

Obwohl zunächst etwas überraschend, erklärt eine kurze Überlegung dies. Einerseits bietet das Erfordernis globalzugewiesener Variablen einen Balken gegen unbeabsichtigte Nebenwirkungen. Wenn Sie dagegen globalfür alle globalen Referenzen erforderlich wären , würden Sie diese globalständig verwenden. Sie müssten als globaljeden Verweis auf eine integrierte Funktion oder auf eine Komponente eines importierten Moduls deklarieren . Diese Unordnung würde die Nützlichkeit der globalErklärung zur Identifizierung von Nebenwirkungen zunichte machen.

https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python


0

Dies bedeutet, dass Sie Folgendes nicht tun sollten:

x = 1

def myfunc():
  global x

  # formal parameter
  def localfunction(x):
    return x+1

  # import statement
  import os.path as x

  # for loop control target
  for x in range(10):
    print x

  # class definition
  class x(object):
    def __init__(self):
      pass

  #function definition
  def x():
    print "I'm bad"

ikostia zählt alle Dinge auf, die Sie nicht verwenden können, wenn Sie global - docs.python.org/reference/…
pycruft

1
@Unode: Ich demonstriere nur alle Fälle, die NikhilRathod in seinem Zitat angegeben hat.
Ikostia

0

Global macht die Variable "Global"

def out():
    global x
    x = 1
    print(x)
    return


out()

print (x)

Dadurch verhält sich 'x' wie eine normale Variable außerhalb der Funktion. Wenn Sie das Global herausnehmen, wird ein Fehler ausgegeben, da keine Variable innerhalb einer Funktion gedruckt werden kann.

def out():
     # Taking out the global will give you an error since the variable x is no longer 'global' or in other words: accessible for other commands
    x = 1
    print(x)
    return


out()

print (x)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.