Globale und Lokale Variablen

Earth and moon, signifying global and local Python behandelt globale und lokale Variablen in einer eigenwilligen Art. Während in vielen anderen Programmiersprachen Variablen automatisch global sind, wenn man sie nicht explizit als lokal deklariert, ist dies in Python genau anders herum. Die zugrundeliegende Idee besteht darin, dass die Benutzung von globalen Variabeln generell als schlechter Programmierstil betrachtet wird, weil dadurch viele Fehler und Seiteneffekte auftreten können. In den meisten Fällen, in denen man versucht ist, eine globale Variable zu verwenden, kann man den gewünschten Effekt besser mittels eines Funktionsparameters realisieren oder durch die Rückgabe eines Wertes mittels eines return-Wertes. Wie auch in vielen anderen Fällen, wird hier durch das Design von Python ein guter Programmierstil gewissermaßen erzwungen.

Das bedeutet, dass jede Variable, die man innerhalb einer Funktion definiert, automatisch einen lokalen Gültigkeitsbereich hat. Das bedeutet, dass was immer man mit dieser Variable innerhalb der Funktion macht, keinen Einfluss auf andere Variablen außerhalb der Funktion hat, auch wenn diese den gleichen Namen haben. Der Funktionsrumpf ist also der Gültigkeitsbereich einer solchen Variablen.

Um keine Missverständnisse aufkommen zu lassen: Variablen müssen nicht deklariert werden, wie dies in anderen Sprachen wie C und Java üblich ist. Variablen werden in Python implizit deklariert, wenn man sie definiert, d.h. ihnen einen Wert zuweist. Eine Variable erhält automatisch den richtigen Datentyp. Bei Problemen mit dieser Thematik empfehlen wir unser Kapitel über "Datentypen und Variablen", siehe Links auf der linken Seite.

Globale und lokale Variablen in Funktionen in Beispielen

Im folgenden Beispiel zeigen wir, wie globale Variablen innerhalb des Funktionsrumpfes benutzt werden können. Allerdings nur "lesend", also ohne den Wert zu ändern:

def f(): 
    print(s) 
s = "I love Paris in the summer!"
f()
Die Variable s wird definiert, in dem ihr die Zeichenkette "I love Paris in the summer!" zugeordnet wird. Diese Definition erfolgt vor dem Funktionsaufruf f(). Der Funktionsrumpf von f() besteht nur aus der "print(s)"-Anweisung. Weil es keine lokale Variable s gibt, d.h. keine Zuweisung an s innerhalb des Funktionsrumpfes von f, wird der Wert der globalen Variablen s benutzt. Dieser Wert kann natürlich nicht verändert werden, wie wir weiter unten in diesem Kapitel sehen werden.
Es wird also der String "I love Paris in the summer!" ausgegeben.

Es stellt sich aber die Frage, was passiert, wenn wir den Wert von s innerhalb der Funktion von f() verändern. Wird dies eine Auswirkung auf die globale Variable s haben? Wir testen dies im folgenden kleinen Skript:
def f(): 
    s = "I love London!"
    print(s) 

s = "I love Paris!" 
f()
print(s)

Es erfolgt folgende Ausgabe:
I love London!
I love Paris!

Wie sieht es aber aus, wenn wir das erste Beispiel mit dem zweiten Beispiel kombinieren, d.h. wir also zuerst auf s mittels print zugreifen, in der Hoffnung den globalen Wert zu erhalten, und dann s einen neuen Wert zuweisen? Indem wir s einen Wert zuweisen können, machen wir s zu einer lokalen Variable. Dadurch gäbe es s innerhalb des Funktionsrumpfes sowohl als globale als auch als lokale Variable. Python lässt diese Mehrdeutigkeit nicht zu und es kommt zu einer Fehlermeldung, wie wir im folgenden Beispiel sehen können:
>>> def f(): 
...   print(s)
...   s = "I love London!"
...   print(s)
... 
>>> s = "I love Paris!"
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
UnboundLocalError: local variable 's' referenced before assignment
>>> 
Eine Variable kann nicht sowohl lokal als auch global innerhalb des gleichen Blocks, hier der Funktionsrumpf, sein. Deswegen betrachtete Python s als eine lokale Variable innerhalb des Rumpfes. Da nun auf diese lokale Variable zugegriffen wird, bevor sie definiert worden ist, sie also noch keinen Wert erhalten hat, erfolgt die Fehlermeldung.

Man kann jedoch auf globale Variablen "schreibend" innerhalb einer Funktion zugreifen. Dazu muss man sie jedoch explizit mittels des Schlüsselwortes "global" als global deklarieren. Wir können dies im folgenden Beispiel sehen:
def f():
    global s
    print(s)
    s = "Zur Zeit nicht, aber Berlin ist auch toll!"
    print(s)


s = "Gibt es einen Kurs in Paris?" 
f()
print(s)

Damit haben wir die Mehrdeutigkeit beseitigt. Die Ausgabe :-) - sieht nun wie folgt aus:
Gibt es einen Kurs in Paris?
Zur Zeit nicht, aber Berlin ist auch toll!
Zur Zeit nicht, aber Berlin ist auch toll!

Auf lokale Variablen einer Funktion kann von außen nicht zugegriffen werden:
def f():
    s = "I am globally not known"
    print(s) 

f()
print(s)

Wenn man dieses Skript startet, erhält man folgende Ausgabe mit Fehlermeldung:
monty@python:~$ python3 ex.py 
I am globally not known
Traceback (most recent call last):
  File "ex.py", line 6, in <module>
    print(s)
NameError: name 's' is not defined
monty@python:~$ 
Das folgende Beispiel zeigt eine wilde Kombination von lokalen und globalen Variablen und Funktionsparametern, um die obigen Sachverhalte nochmals per Beispiel zu vertiefen:
def foo(x, y):
    global a
    a = 42
    x,y = y,x
    b = 33
    b = 17
    c = 100
    print(a,b,x,y)

a,b,x,y = 1,15,3,4
foo(17,4)
print(a,b,x,y)

Wir erhalten folgende Ausgaben:
42 17 4 17
42 15 3 4