Eigener Datentyp -> Globale Variable?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Sonntag 14. März 2010, 02:17

Hey.
Warum ist das so?

Code: Alles auswählen

>>> class foo():
	    def __init__(self):
		    self.foo = 100

>>> a = foo()
>>> b = 100
>>> def bla():
	    a.foo = 10

>>> def blubb():
	    b = 10

>>> bla()
>>> a.foo
10
>>> blubb()
>>> b
100
BlackJack

Sonntag 14. März 2010, 02:33

@Nocta: Weil so halt die Scoping-Regeln von Python funktionieren. Wenn man irgendwo in einer Funktion (oder Methode) einen Namen bindet, ist der lokal.

In `bla()` veränderst Du das Objekt was an `a` gebunden ist und in `blubb()` bindest Du einen Wert an einen lokalen Namen `b`.
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Sonntag 14. März 2010, 02:41

Hm okay.
Wenn das so ist, muss ich's wohl hinnehmen, auch wenn ich das seltsam finde :D
Ich dachte bisher immer, dass man in Funktionen zwar Variablen aus einer höheren Ebene lesen darf, aber nicht verändern kann.
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Sonntag 14. März 2010, 08:27

Du veränderst ja nicht die "Variable a", schließlich ist das Objekt, das an den Namen 'a' gebunden ist ja vorher wie nachher das selbe. Du änderst lediglich ein Attribut, und das ist erlaubt.
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Sonntag 14. März 2010, 11:45

Ja, der Unterschied zwischen dem, was ich mache ist mir klar.
Aber dass ich ein Objekt, welches sich eine Ebene über der Funktion befindet, innerhalb einer Funktion verändern kann, hat mich gewundert.

Aber so gesehn ist das Verhalten gar nicht mal schlecht. Wenn man auf objekt.attribut zugreift erhält man entweder einen Error, oder aber man greift auf ein Objekt zurück, welches auf einer höheren Ebene existiert.
Für mich ist das zwar ein bisschen zu "tolerant", weil das wieder teilweise globale Variablen bzw "globale Objektattribute" fördert, aber naja, man muss schließlich selbst wissen, wie man programmiert.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Sonntag 14. März 2010, 11:52

Es gibt sogar drei Namensräume, die man beachten muss: Den Lokalen, den Globalen und den Namensraum, der zur Definitionszeit im umliegenden Block aktiv war.

Code: Alles auswählen

>>> a, b, c = 1, 1, 1
>>> def outer():
...   b = 2
...   def inner():
...     c = 3
...     print a, b, c
...   return inner
... 
>>> inner = outer()
>>> inner()
1 2 3
Zum Glück haut einem Python aber einen Fehler um die Ohren, wenn man in einem Block aus versehen lokale und nicht-lokale variablen mit dem gleichen Namen verwendet. Das merkst du z.B. wenn du Zeile 5 und 6 in meinem Beispiel vertauscht.
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
snafu
User
Beiträge: 5644
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Sonntag 14. März 2010, 11:58

Nocta hat geschrieben:Aber dass ich ein Objekt, welches sich eine Ebene über der Funktion befindet, innerhalb einer Funktion verändern kann, hat mich gewundert.
Naja, "Verändern" ist relativ:

Code: Alles auswählen

>>> class Foo(object): pass
... 
>>> foo = Foo()
>>> def modify_foo(): foo.bar = 42
... 
>>> id(foo)
3077101996L
>>> hasattr(foo, 'bar')
False
>>> modify_foo()
>>> foo.bar
42
>>> id(foo)
3077101996L
shcol (Repo | Doc | PyPi)
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Sonntag 14. März 2010, 12:04

Naja, für mich ist das verändert :D

Dass es kein neues Objekt ist, ist klar, weil das anscheinend das einzige ist, was nicht geht :)
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Sonntag 14. März 2010, 12:51

Nocta hat geschrieben:Naja, für mich ist das verändert :D

Dass es kein neues Objekt ist, ist klar, weil das anscheinend das einzige ist, was nicht geht :)
Das hier ist der Punkt, wo dein Verständnis von Variablen in Python zusammenbrechen sollte ;-) Du musst dir klar machen, was snafu schon versucht hat: den Unterschied zwischen "echten" Variablen und an Namen gebundene Objekte.
Das Leben ist wie ein Tennisball.
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Sonntag 14. März 2010, 12:53

Und was ist dann eine "echte" Variable? ;)
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Sonntag 14. März 2010, 12:57

Nur damit das auch geklärt ist :twisted:

Code: Alles auswählen

>>> a = 100
>>> def blubb():
...     global a
...     a = 10
...     
>>> a
100
>>> blubb()
>>> a
10


verwenden solltest du global aber nicht, dass kann ganz schön schief gehen
Wenn man global braucht, ist es (meiner Meinung nach) Zeit für eine Klasse
the more they change the more they stay the same
Benutzeravatar
snafu
User
Beiträge: 5644
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Sonntag 14. März 2010, 13:18

"Echte Variable" ist doof gewählt. Es geht darum, ob ein neues Objekt an den Namen gebunden wurde oder ob Attribute des vorhandenen Objekts verändert wurden. Aber eigentlich erkennt man das ja auch durch Anschauen der Beispiele und Ausprobieren. Und du hast es auch selbst erkannt. :)
shcol (Repo | Doc | PyPi)
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Sonntag 14. März 2010, 13:25

Ja, das Verhalten hab ich mittlerweile erkannt.

Neues Objekt an den Namen binden: Nein
An den Namen gebundenes Objekt ändern: Ja

Das werd ich dann fortan als Tatsache ansehen, mich hat es halt etwas stutzig gemacht. Dass man Objekte von außerhalb lesen kann, war mir schon bekannt und steht an mehreren Stellen im Internet (auch hier im Forum). Aber da ist irgendwie nie die Rede davon, dass man das Objekt auch ändern (also die Attribute schreiben) kann.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Sonntag 14. März 2010, 13:50

Nocta hat geschrieben: Neues Objekt an den Namen binden: Nein
An den Namen gebundenes Objekt ändern: Ja
Soweit richtig.
Nocta hat geschrieben:Das werd ich dann fortan als Tatsache ansehen, mich hat es halt etwas stutzig gemacht. Dass man Objekte von außerhalb lesen kann, war mir schon bekannt und steht an mehreren Stellen im Internet (auch hier im Forum). Aber da ist irgendwie nie die Rede davon, dass man das Objekt auch ändern (also die Attribute schreiben) kann.
Eigentlich ist das 'ändern können' die Regel und das 'nicht ändern können' die Ausnahme. Objekte sind in Python nämlich grundsätzlich "mutable", also veränderbar. Integer, Floats, Strings, Tupel u.s.w. sind aber explizit 'immutable', also nicht veränderbar. Dieser Begriff, der auch oft in der Dokumentation vor kommt, ist in Python ziemlich wichtig.

Immutable bedeutet: Du kannst eine neue Version an den gleichen Namen binden, aber du kannst nicht den Wert selbst verändern. Darum bist du gezwungen, `a=1` statt `a.set(1)` zu schreiben.
Bottle: Micro Web Framework + Development Blog
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Sonntag 14. März 2010, 14:13

Okay, das leuchtet so weit ein.
Ich muss mich nur von dem Gedanken trennen, dass die Namensräume wie in anderen Sprachen funktionieren und mir deine Regel
Eigentlich ist das 'ändern können' die Regel
einprägen :)
Antworten