Problem mit globalen und lokalen Werten

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.
AchtungHuPe
User
Beiträge: 5
Registriert: Samstag 27. November 2010, 22:46

Hallo,
ich bin dabei mir rein hobbymäßig Python beizubringen und gleichzeitig auch meinem Sohn einen Einstieg ins programmieren zu zeigen.
Bei einer Sache stehe ich jetzt aber an: Warum liefert die Funktionen den veränderten Wert von anzahl nicht?
Zur Veranschaulichung mal das ganze Programm auf's notwendigste gekürzt.

Code: Alles auswählen

liste =[['.','.'] , ['.','.']]
anzahl = 0

def listemod(anzahl):
    liste[0][1] = 'X'
    anzahl += 1
    print('anzahl (inside):',anzahl)
    return anzahl


# main
print('Liste vorher:', liste)
print('anzahl (outside):',anzahl)
listemod(anzahl)
print('Liste nachher:', liste)
print('anzahl (outside):',anzahl)
Probelauf

Code: Alles auswählen

>>> 
Liste vorher: [['.', '.'], ['.', '.']]
anzahl (outside): 0
anzahl (inside): 1
Liste nachher: [['.', 'X'], ['.', '.']]
anzahl (outside): 0
>>> 
Neben dem aktuellen Problem außerhalb der Funktion nicht den geänderten Wert von anzahl zu haben, verstehe ich nicht warum dagegen das ändern eines Listenwertes ohne weiteres Tamtam (Parameterübergabe, return) so einfach funktioniert.

Was ist falsch oder besser wie gehts richtig?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Listen sind veraenderbar, Zahlen nicht.
Das ist nicht das Problem, sondern ist fuer das Phaenomen verantwortlich - zumindest waer das der Fall, wenn der Funktionsparameter anders heissen wuerde. Man kann globalen (oder aeusseren) Namen keine neuen Objekte zuweisen ohne `global' (oder `nonlocal') zu verwenden. Die Liste wird aber wie gesagt direkt veraendert.

`anzahl' betritt die Funktion als Parameter, nicht als der globale Namen, darum kann sich der globale Namen gar nicht veraendern, weil auf ihn gar nich zugegriffen wird. `print(listemod(anzahl))` wird dir auch 1 ausgeben. Genauso wird `anzahl = listemod(anzahl)' funktionieren.

P.S. Man sollte das Veraendern globalen Objekten moeglichst vermeiden (`global' erst recht)
BlackJack

@AchtungHuPe: Die Funktion gibt den Wert zurück -- Du machst dann aber nichts damit. Du müsstest ihn auch wieder an das globale `anzahl` zuweisen:

Code: Alles auswählen

anzahl = listemod(anzahl)
Bei der Liste veränderst Du das Listenobjekt. Das ist etwas anderes als die Bindung zwischen Name und Objekt zu ändern. `liste` ist vor und nach dem Aufruf von `listemod()` immer an das selbe Listenobjekt gebunden. Genau wie in Deinem Beispiel `anzahl` an das selbe Objekt gebunden ist. Im Gegensatz zu Listen kann man Zahlen aber nicht verändern.
AchtungHuPe
User
Beiträge: 5
Registriert: Samstag 27. November 2010, 22:46

Danke für die Antworten, das ist für mich nachvollziehbar und verständlich.

@cofi: Auf `anzahl = listemod(anzahl)' " bin ich in der Zwischenzeit durch grübeln auch gekommen.
Bei der Recherche habe ich über global folgendes gelesen und es war so überzeugend, dass ich ohne auskommen wollte
Alles was von einer Funktion zum Arbeiten benötigt wird, sollte man an
die Funktion als Parameter übergeben.

Alles was von einer Funktion verändert werden soll, sollte man als
Rückgabe (mit return) zurück geben.

So wird kein "global" gebraucht und alles was passiert ist
offensichtlicher denn je. Schon beim Aufruf der Funktion ist klar, dass
die Variable "my_value" mit einem neuen Wert belegt wird. Man muss sich
dazu die Funktion nicht durchlesen.
@all: Im richtigen Programm ist der Hauptzweck der Funktion die Liste zu verändern. Der Zähler ist nur ein Nebenprodukt um eine bestimmte Bedingung zu prüfen.

So war es gedacht:

Code: Alles auswählen

while spiel =='begonnen':
    benutzereingabe()
    computerzug()
Mit o.a. Zuweisung funktioniert es zwar aber das führt dabei zu Code der, zumindest auf mich, seltsam wirkt

Code: Alles auswählen

while spiel == 'begonnen':
    anzahl = spielerzug(anzahl)
    anzahl = computerzug(anzahl)
Die zweite Variante ist schon übler Stil, oder?
Also doch die global-Variable oder ein ganz anderer Ansatz. Ich könnte statt dem Zähler eine weitere Liste manipulieren, die hätte dann nur ein Element das als 'Zählvariable' verwendet wird. Ist das wirklich besser?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

AchtungHuPe hat geschrieben:Bei der Recherche habe ich über global folgendes gelesen und es war so überzeugend, dass ich ohne auskommen wollte
Meine Erwaehnung von `global` war auch keinesfalls eine Empfehlung, sondern ich habs zur Illustration benutzt. Wenn man `global` nutzt, macht man zu 99,9% etwas falsch und den Rest kann man auch anders abdecken.

Code: Alles auswählen

while spiel == 'begonnen':
    anzahl = computerzug(spielerzug(anzahl))
Aber das ruft fuer mich lautstark nach Klassen.

Edit: `spiel` laesst sich doch bestimmt besser durch False/True ausdruecken oder?
AchtungHuPe
User
Beiträge: 5
Registriert: Samstag 27. November 2010, 22:46

Bei Klassen bin ich noch nicht angekommen :(

Die Sache mit dem Zähler funktioniert nun. Ich lasse `anzahl´nicht innerhalb der Funktion mitlaufen sondern beim aufrufen der Funktion in der Hauptschleife, das ist hier zulässig. Alternativ kann man es auch mit einer Scheife realisieren, glaube bin gestern voll auf der Leitung gestanden was das betrifft :-/

Momentan beschäftige ich mich mit dem Spielende. `spiel´ habe ich auf boolen umgestellt. Die Funktion zum auswerten des Zuges erkennt zwar die Gewinnsituation aber die Hauptschleife stoppt trotzdem nicht. Wahrscheinlich ein ähnliches Problem wie oben nur ohne Fehlermeldung. Da komme ich jetzt schon selber dahinter ;-)


Muss mich nochmal bedanken für die raschen und guten Antworten, hat mir sehr geholfen!
funkheld
User
Beiträge: 258
Registriert: Sonntag 31. Oktober 2010, 09:26

Mit Python kannst du keinen einen Einstieg in das Programmieren zeigen ,das wird ein Irrgarten.
Python ist eine Scriptsprache mit der man nur durch die Brust ins Auge etwas vernünftiges Zaubern kann.
Wenn du anderen erzählst, mit was du proggen tust und dann "Python" nennst, bekommst du nur ein müdes lächeln zurück. :D

Python ja, nur wenn man programmieren kann , ansonsten Finger weg.
90% der Begriffe von Python sind in der allgemeinen Programmierumgebung unbekannt.

Ich kann als Sprache XBLite empfehlen.

Gruss
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Im Gegensatz zu funkheld halte ich Python durchaus für eine gerade auch für Anfänger geeignete Sprache. Das 90% irgendwelcher Begriffe anders sein sollten, halte ich für falsch. Die Unterscheidung zwischen Script- und Programmiersprache ist künstlich und irrelevant. Ich persönlich finde Python auch von der Syntax her einfacher und eleganter als ein Basic-Dialekt.

Das Scoping von Variablen ist bei Python zugegeben ungewöhnlich (aber schlüssig). Darüber ist AchtungHuPe ja schon gestolpert. Die meisten Sprachen folgen hier dem Prinzip der lexikografischen Bindung. Die restliche Semantik ist wie bei allen anderen imperativen Sprachen - keine Überraschungen. Python erlaubt neben einfacher prozeduraler Programmierung auch Ausflüge in die objektorientierte und (mit etwas Selbstbeschränkung) die funktionale Programmierung.

Stefan
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

funkheld hat geschrieben:90% der Begriffe von Python sind in der allgemeinen Programmierumgebung unbekannt.
Aha. Beispiele?
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

funkheld hat geschrieben: Wenn du anderen erzählst, mit was du proggen tust und dann "Python" nennst, bekommst du nur ein müdes lächeln zurück. :D
Meist von von Leuten, die mit PHP zu tun haben...

Ich fang mal an: 9 Sachen, die es "nur" in Python gibt:

1. Einrückung durch Whitespace
2. Explizit ist besser als Implizit
...
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
AchtungHuPe
User
Beiträge: 5
Registriert: Samstag 27. November 2010, 22:46

Hallo funkheld,

"Einstieg in Programmierung"

Danke für Deinen, sicher gut gemeinten, Tip zu XBLite.
Andererseits möchte ich meinen 13-jährigen jetzt ja nicht zum Profihacker ausbilden der vom coden lebt ....

Es geht mir vielmehr darum ihm zu zeigen was Programmieren eigentlich ist. Also Probleme/Aufgabenstellungen systematisch in Teile zerlegen, zu hinterfragen ob die Aufgabenstellung vollständig ist (und zu erkennen was fehlt) sowie ein Werkzeuge zur Umsetzung anzuwenden lernen.
Mit Python kann ich genausogut prozedural an Aufgaben herangehen, Datentypen und Ablaufsteuerung erklären und über Funktionen mich dem Wesen der Objektorientierung nähern.

Dafür war Python bis jetzt nicht die schlechteste Wahl. Ist cool zuzusehen wie er versteht warum was nicht funktioniert weil zB wiedermal die " ' " um einen String fehlten oder auch dass er manchmal pragmatischere Ansätze findet als ich selber :D
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

AchtungHuPe hat geschrieben:Danke für Deinen, sicher gut gemeinten, Tip zu XBLite.
Andererseits möchte ich meinen 13-jährigen jetzt ja nicht zum Profihacker ausbilden der vom coden lebt ....
Lass dich bitte nicht von funkheld verwirren. XBlite kennt keiner, benutzt keiner und viel schlimmer gibts das nur für Windows. Vermutlich einer der letzten Basic-Dialekte den ich irgendwem als Einstieg empfehlen würde. Je weniger esoterisch die Sprache ist, desto mehr Doku und Hilfe findet man i.d.R.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

AchtungHuPe hat geschrieben:Andererseits möchte ich meinen 13-jährigen jetzt ja nicht zum Profihacker ausbilden der vom coden lebt ....
Evtl. wäre das was für euch: Python für Kids. In der aktuellen Auflage sogar schon für Python 3.1. Der Zugang über die Turtle-Grafik kann gerade für junge Programmierer motivierend sein. Ähnlich (allerdings ohne Buch, dafür mit kostenlosem dt. Tutorial): Das frog-Modul.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

jbs hat geschrieben:Ich fang mal an: 9 Sachen, die es "nur" in Python gibt:

1. Einrückung durch Whitespace
Mir fällt spontan Occam ein, eine Sprache aus den 80ern (noch vor Python), die Einrückung für Blöcke nutzte. Und ohne das jetzt nachzugucken, Haskell kann das doch alternativ zu Klammern ebenfalls.

Also nur noch 8 Sachen...

Stefan
BlackJack

Nemerle und CoffeScript würden mir da noch zusätzlich einfallen.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

sma hat geschrieben:
jbs hat geschrieben:Ich fang mal an: 9 Sachen, die es "nur" in Python gibt:

1. Einrückung durch Whitespace
Mir fällt spontan Occam ein, eine Sprache aus den 80ern (noch vor Python), die Einrückung für Blöcke nutzte. Und ohne das jetzt nachzugucken, Haskell kann das doch alternativ zu Klammern ebenfalls.

Also nur noch 8 Sachen...

Stefan
Deshalb steht das `nur` auch in `"`.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Nemerle und CoffeScript würden mir da noch zusätzlich einfallen.
Außerdem Haml und Jade.

Und explizit ist besser als implizit gibts auch in Java, einer der bekanntesten Programmiersprachen überhaupt. Also nur noch 7 Sachen, bin gespannt auf den Rest der Liste.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Für HAML, Jade und CoffeeScript gilt aber, dass die allesamt nach Python erfunden wurden, zum Teil sogar Python als Inspirationsquelle nennen. Daher nannte ich extra Occam. Zu "explizit vs. implizit" wollte ich nichts sagen, denn das ist weniger ein Feature als eine Philosophie. Und hier gibt es wohl eher den Streit zwischen "es gibt einen Weg" und "es gibt mehrere Wege" (MTOWTDI oder so) Denkschulen, den man besser eindeutig auf Sprachen und ihr Erscheinungsdatum abbilden kann. Scheme war z.B. auch Reaktion auf die Vielfalt von Lösungswegen in CommonLisp. Dennoch ist Perl das poster child für MTOWTDI.

Aber wo bleiben Sie denn nun, die besonderen Eigenschaften von Python? List comprehensions sind es schon mal nicht. Objektorientierung auch nicht. Lambda jedenfalls nicht, das gab es auch schon in den frühsten Lisp-Dialekten. Möglicherweise der "if/else"-Operator, den hatte ich vor Python so noch in keiner anderen Sprache gesehen. Alle anderen stellen immer die Bedingung nach vorne.

Stefan
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

jbs hat geschrieben:Ich fang mal an: 9 Sachen, die es "nur" in Python gibt:

1. Einrückung durch Whitespace
2. Explizit ist besser als Implizit
...
Äh, mit was rücken denn die anderen Sprachen ein? Blackspace?
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

bords0 hat geschrieben:
jbs hat geschrieben:Ich fang mal an: 9 Sachen, die es "nur" in Python gibt:

1. Einrückung durch Whitespace
2. Explizit ist besser als Implizit
...
Äh, mit was rücken denn die anderen Sprachen ein? Blackspace?
In der Regel (u. a. Java, C, C++, C#) werden Blöcke mit { } markiert. Einrückung ist völlig egal..
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
Antworten