Seite 1 von 1

Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Sonntag 9. Juni 2019, 20:39
von Atalanttore
Hallo

Auf einer Webseite habe ich Python 2-Code gesehen, wo die Änderung des Wertes einer vermeintlich lokalen Variable den Wert einer globalen Variable ändert.

Code:

Code: Alles auswählen

# a global array
aa = [0, 1, 2]
print("Global:", id(aa))


def f():
    aa[0] = 88   # this is ok. global array will be updated
    print("Funktion f():", id(aa))


def g():
    aa = []     # WRONG! global array will NOT be updated
    print("Funktion g():", id(aa))


f()
print(aa)                        # prints [88, 1, 2]

g()
print(aa)                        # prints [88, 1, 2]
Warum ist die Variable `aa` in der Funktion `f()` eine globale Variable?

Gruß
Atalanttore

Re: Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Sonntag 9. Juni 2019, 21:00
von Sirius3
Weil ›aa‹ in ›f‹ nicht definiert wird, also irgendwo außerhalb, ergo global, definiert sein muß.
Nur die Kommentare sind durcheinander, im ersten Fall sollte FETT ”wrong“ stehen, weil man nicht wild Listen verändern sollte, ›g‹ ist ok, da passiert nicht schlimmes.

Re: Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Sonntag 9. Juni 2019, 21:06
von __blackjack__
@Atalanttore: Warum sollte `aa` in `f()` keine globale Variable sein?

Die Entscheidung ob ein Name lokal ist oder nicht trifft der Compiler wenn er über eine Zuweisung an den Namen findet. In `f()` gibt es keine Zuweisung an den Namen → `aa` ist nicht lokal. In `g()` gibt es eine Zuweisung an den Namen → `aa` ist lokal.

Wenn Du das bisher nicht gewusst hast, dann frage ich mich wie Du so lange ”unfallfrei” mit Python klar gekommen bist. Das ist ja nicht gerade unwichtig. :-)

Re: Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Sonntag 9. Juni 2019, 21:20
von Atalanttore
@Sirius3 & __blackjack__: Also ist die Änderung des Wertes eines Elements in einer Liste über den Index keine Zuweisung?

Gruß
Atalanttore

Re: Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Sonntag 9. Juni 2019, 21:28
von __blackjack__
@Atalanttore: Doch das ist eine Zuweisung. Aber keine Zuweisung an den *Namen*. Um den geht es ja.

Re: Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Sonntag 9. Juni 2019, 21:47
von __deets__
Murmeltiere. Überall Murmeltiere.

@Attalantore: Pythons Objekte können veränderlich oder nicht sein. Eine Liste ist es. Und da du an die Liste auf Moduleben rankommst, kannst du sie auch verändern.

Was du NICHT kannst (ohne global) ist dem Namen aa ein neues Objekt zuweisen. Und das ist der Unterschied. Jetzt gibt’s natürlich so ein paar Schlaumeier (Alfons M, anybody?) die sagen “wo nicht global dran steht, ist nicht global drin”.

Und das ist natürlich Unfug. Dieses Vorgehen mit aa ist keine deut besser. Nicht das Schlüsselwort global ist böse. Sondern das Konzept, in einer Funktion Zustand zu ändern, der dauerhaft geändert bleibt.

Re: Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Montag 10. Juni 2019, 18:32
von Atalanttore
__deets__ hat geschrieben: Sonntag 9. Juni 2019, 21:47 Was du NICHT kannst (ohne global) ist dem Namen aa ein neues Objekt zuweisen. Und das ist der Unterschied. Jetzt gibt’s natürlich so ein paar Schlaumeier (Alfons M, anybody?) die sagen “wo nicht global dran steht, ist nicht global drin”.
Meinst du mit "Objekt zuweisen" dem bestehenden Zeiger auf einen Speicherbereich einen anderen neuen Speicherbereich zuzuweisen?

Gruß
Atalanttore

Re: Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Montag 10. Juni 2019, 19:01
von sparrow
Mit "Objekt zuweisen" meint __deets__ schlicht

Code: Alles auswählen

aa = neues Objekt
Denn damit weist man einem Namen ein Objekt zu.

Re: Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Montag 10. Juni 2019, 20:34
von snafu
@Atalanttore: Zuweisungen gelten grundsätzlich nur für den lokalen Namensraum. Innere Namensräume (d.h. diejenigen "unterhalb" dieses Namensraums) können entscheiden ob sie eine eigene Zuweisung machen oder ob sie eine "höher gelegene" Zuweisung verwenden. Zur Veranschaulichung hier dargestellt mit inneren Funktionen:

Code: Alles auswählen

def f():
    x = 1
    def g():
        x = 2
        print(f'Inside g(): x is {x}')
        return x
    print(f'Return value of g(): {g()}')
    print(f'Original x inside f(): {x}')
    return x

def f2():
    x = 1
    def g():
        print(f'g() uses outer x: {x}')
        return x
    print(f'Return value of g(): {g()}')
    print('Adding return value to x...')
    x += g()
    print(f'Outer x is now {x}')
    print('Calling g() again...')
    print(f'Return value of g(): {g()}')
    return x
Bei deinem eingangs gezeigten Code-Beispiel wird ähnlich wie hier in f2() einfach das aa aus dem äußeren Namensraum angesprochen. Sobald man es einmal hat, unterscheiden sich die Zugriffsmöglichkeiten nicht vom "eigenen" Namensraum des Objekts. Eine Liste kann also im inneren Namensraum auf die gleiche Weise verändert werden wie in einem äußeren Namensraum. Die Regeln ob etwas lokal ist, gelten nur für den Zugriff auf den eigentlichen Bezeichner, nicht aber für das Verhalten des Objektes. Denn dieses weiß grundsätzlich nicht, in welchem Namensraum es "geholt" wurde (obskure Tricks mit dem Aufruf-Stack mal ausgenommen). Ist es so etwas klarer für dich...?

Re: Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Montag 10. Juni 2019, 20:44
von snafu
Atalanttore hat geschrieben: Montag 10. Juni 2019, 18:32
__deets__ hat geschrieben: Sonntag 9. Juni 2019, 21:47 Was du NICHT kannst (ohne global) ist dem Namen aa ein neues Objekt zuweisen. Und das ist der Unterschied. Jetzt gibt’s natürlich so ein paar Schlaumeier (Alfons M, anybody?) die sagen “wo nicht global dran steht, ist nicht global drin”.
Meinst du mit "Objekt zuweisen" dem bestehenden Zeiger auf einen Speicherbereich einen anderen neuen Speicherbereich zuzuweisen?
Das hast du jetzt wahrscheinlich irgendwo ergoogelt. Das Konzept von Zeigern und Speicherbereichen kennt Python nicht. Solche Erklärungen taugen eher für Sprachen wie C oder C++. Python kennt nur Objekte und Namen. Was die konkrete Python-Implementierung intern macht, sollte hierbei keine Rolle spielen.

Re: Lokale Variable in Funktion wird automatisch zu globaler Variable

Verfasst: Montag 10. Juni 2019, 20:49
von Atalanttore
@snafu: Danke für den Code und die Erklärung. Es ist jetzt "etwas" klarer.

Gruß
Atalanttore