Seite 1 von 1
Python Variablenfehler
Verfasst: Samstag 28. Mai 2011, 14:49
von UnSpeed
Hey Leute,
ich bin noch relativ neu mit Python zugange, allerdings nicht mit Programmierung an sich, deshalb macht mich auch das folgende Problem ein bisschen stutzig:
Code: Alles auswählen
import sys, random
def menue():
level_int = 5
spielen = True
while spielen:
print "(N)eues Spiel\n(L)evelauswahl\n(A)nleitung\n(B)eenden"
eingabe = str(raw_input(""))
if eingabe == "n" or eingabe == "N":
#Hier beginnt ein neues Spiel
print level_int
zahl = random.randint(0,level_int*10)
print zahl
elif eingabe == "l" or eingabe == "L":
#Hier kommt die Levelauswahl
print "Es gibt drei Level:\n(L)eicht\n(M)ittel\n(S)chwer"
level = str(raw_input(""))
if level == "l" or eingabe == "L":
level_int = 1
elif level == "m" or eingabe == "M":
level_int = 5
elif level == "s" or eingabe == "S":
level_int = 10
else:
print "Fehlerhafte Eingabe. Gehe zu Hauptmenue"
print level_int
menue()
elif eingabe == "a" or eingabe == "A":
#Hier kommt die Anleitung
print ""
elif eingabe == "b" or eingabe == "B":
#Hier wird das Spiel beendet
spielen = False
print "Hallo hier ein kleines Spiel :D"
menue()
Wenn ich jetzt das Programm starte, dann funktioniert auch eigentlich alles, bis auf die Tatsache, dass egal was ich in der Levelauswahl eingebe level_int bei einem neuen Spiel
immer 5
wird.
Denn wenn ich beispielsweise als Level "(L)eicht" auswähle, dann wird level_int auf 1 gesetzt. Starte ich aber danach ein neues Spiel, dann ich level_int wieder automatisch 5...
Syntaxfehler sind keine vorhanden und den Logikfehler sehe ich nicht -.-
Bitte helft mich weiter, ich verzweifel sonst noch
Danke,
UnSpeed
Re: Python Variablenfehler
Verfasst: Samstag 28. Mai 2011, 15:45
von mutetella
Hallo,
nun ja, sobald 'menue()' aufgerufen wird, wird 'level_int' auf 5 gesetzt.
Es dürfte auch kaum möglich sein, das Spiel über b/B zu beenden...
Noch ein Tipp zur Vereinfachung: Statt
würde ich die entweder die eingabe gleich in einen Klein- oder Großbuchstaben umwandeln
Code: Alles auswählen
#entweder
eingabe = str(raw_input('Diese Eingabe wird klein: ')).lower()
#oder
eingabe = str(raw_input('Diese Eingabe wird GROSS: ')).upper()
dann musst Du nur auf einen Groß- oder eben einen Kleinbuchstaben prüfen, oder aber Du überprüfst die Eingabe so:
mutetella
Re: Python Variablenfehler
Verfasst: Samstag 28. Mai 2011, 15:54
von UnSpeed
Mir ist bewusst, dass das beim Aufrufen der Funktion auf 5 gesetzt wird, aber die Variable wird ja innerhalb der Funktion geändert, und DAS ist meine Frage: WARUM ändert sich das trotzdem in 5?
Das mit der eingabe war auch nur eine Notlösung, denn der Befehl .lower() war mir bereits bekannt. Der Befehl in 'aA' da gegen nicht, danke
Und doch, das Spiel lässt sich über b/B beenden, was ja auch logisch ist, weil dadurch die While-Schleife unterbrochen wird, die Funktion normal ausläuft und nach dem Funktionsaufruf nichts mehr folgt.
Leider weiß ich jetzt aber immer noch nicht, wie ich das eigentliche Problem beheben kann...
Re: Python Variablenfehler
Verfasst: Samstag 28. Mai 2011, 16:06
von mutetella
UnSpeed hat geschrieben:Und doch, das Spiel lässt sich über b/B beenden, ...
Stimmt. Mein Fehler, ich dachte, nach Eingabe von b/B geschieht dasselbe wie nach Eingabe von l/L, wo eben Dein Fehler steckt.
Damit meine ich, dass Du nach Eingabe von l/L die 'menue()' von neuem aufrufst und somit nicht zurück zum Schleifenanfang gehst, sondern eine neue Schleife startest. Mit anderen Worten:
Code: Alles auswählen
def menue():
...
level = 5
while spielen:
...
if eingabe in 'lL':
...
menue()
Da kannst Du l/L's auswählen, bis Du schwarz wirst oder irgendwann ein RuntimeError kommt, weil die maximale Rekursionstiefe erreicht ist.
Jetzt klarer?
mutetella
Re: Python Variablenfehler
Verfasst: Samstag 28. Mai 2011, 16:12
von UnSpeed
autsch xD
Allerdings, wenn ich den Code folgend umstelle, dann kann ich offenbar nicht auf die Variable "spielen" zugreifen:
Code: Alles auswählen
import sys, random
level_int = 5
spielen = True
def menue():
while spielen:
print "(N)eues Spiel\n(L)evelauswahl\n(A)nleitung\n(B)eenden"
eingabe = str(raw_input(""))
if eingabe == "n" or eingabe == "N":
#Hier beginnt ein neues Spiel
print level_int
zahl = random.randint(0,level_int*10)
print zahl
elif eingabe == "l" or eingabe == "L":
#Hier kommt die Levelauswahl
print "Es gibt drei Level:\n(L)eicht\n(M)ittel\n(S)chwer"
level = str(raw_input(""))
if level == "l" or eingabe == "L":
level_int = 1
elif level == "m" or eingabe == "M":
level_int = 5
elif level == "s" or eingabe == "S":
level_int = 10
else:
print "Fehlerhafte Eingabe. Gehe zu Hauptmenue"
print level_int
menue()
elif eingabe == "a" or eingabe == "A":
#Hier kommt die Anleitung
print ""
elif eingabe == "b" or eingabe == "B":
#Hier wird das Spiel beendet
spielen = False
print "Hallo hier ein kleines Spiel :D"
menue()
Dann kommt diese Fehlermeldung:
Traceback (most recent call last):
File "ratespiel.py", line 37, in <module>
menue()
File "ratespiel.py", line 5, in menue
while spielen:
UnboundLocalError: local variable 'spielen' referenced before assignment
Edit:
Hat sich erledigt, ich habe einfach die Variablen wieder reingetan und den Funktionsaufruf innerhalb der Funktion gelöscht.
Allerdings verstehe ich dir oben genannte Fehlermeldung noch nicht ganz...
Kann da vllt. bitte noch mal jmd. helfen?
Re: Python Variablenfehler
Verfasst: Samstag 28. Mai 2011, 16:42
von mutetella
Du denkst in die falsche Richtung...
Die Frage ist doch, weshalb muss denn 'menue()' neu aufgerufen werden? Du befindest Dich doch in einer Schleife...
Das was Du machst nennt sich Rekursion, das heißt, eine Funktion ruft sich selbst auf. Macht man z. B. bei Sortieralgorithmen.
Du möchtest aber etwas ganz anderes, nämlich nach der Levelauswahl wieder
zurück zur Eingabe. Und um zur Eingabe zurückzukehren musst Du doch nicht erneut 'menue()' aufrufen.
mutetella
Re: Python Variablenfehler
Verfasst: Samstag 28. Mai 2011, 17:17
von mutetella
UnSpeed hat geschrieben:Allerdings verstehe ich dir oben genannte Fehlermeldung noch nicht ganz...
Das liegt daran, dass der Name 'spielen' außerhalb der Funktion 'menue()' erstellt wurde und daher innerhalb von 'menue()' nicht gesehen werden kann.
Wenn du innerhalb einer Funktion auf Namen zugreifen möchtest, die außerhalb erstellt wurden, dann musst Du diese Namen an die Funktion übergeben. In Deinem Fall könnte das so aussehen:
Code: Alles auswählen
import sys, random
level = 5
spielen = True
def menue(level, spielen):
...
menue(level, spielen)
Dabei geschieht folgendes: In dem Modul, in dem sich 'menue()' befindet, wird 'level' an die Zahl 5 und 'spielen' an den Wert True gebunden.
Durch den Aufruf von 'menue(level, spielen)' wird die Zahl 5 und der Wert True an die Funktion 'menue()' übergeben und dort an die Namen 'level' und 'spielen' gebunden. Wenn Du nun innerhalb der Funktion die Werte von 'level' oder 'spielen' änderst, gilt das auch nur innerhalb der Funktion, auf Modulebene bleibt alles beim alten. Auch wenn das nicht ganz korrekt ist kann man sagen, dass die Namen 'level' und 'spielen' doppelt existieren, einmal auf Modul- und einmal auf Funktionsebene.
Wenn Du 'level' und 'spielen' auch auf Modulebene an die Werte, die innerhalb der Funktion gelten, angleichen möchtest, könntest Du das z. b. so erreichen:
Code: Alles auswählen
import sys, random
level = 5
spielen = True
def menue(level, spielen):
...
return (level, spielen)
level, spielen = menue(level, spielen)
mutetella
Re: Python Variablenfehler
Verfasst: Samstag 28. Mai 2011, 21:03
von UnSpeed
Danke, ich weiß, was Rekursion ist
Ich programmiere schon seit einigen Jahre und kenne grundspezifisch auch viele Strukturen (wie eben beispielsweise Rekursion

).
Ich brauchte nur die Information, dass Variablen, die ausserhalb definiert worden sind, nicht ohne weiteres in eine Funktion übernommen werden können.
Da liegt übrigens einer der Unterschiede zu Java
Damit hat sich dieses Thema erledigt --> Danke

Re: Python Variablenfehler
Verfasst: Samstag 28. Mai 2011, 21:43
von mutetella
UnSpeed hat geschrieben:Da liegt übrigens einer der Unterschiede zu Java
Meines Halbwissens nach gilt das bei Java aber nur für statische Variablen, die es in dieser Form bei Python nicht gibt. Alle anderen Variablen sind ebenfalls sehr wohl an den Namensraum ihrer Deklaration gebunden.
mutetella
Re: Python Variablenfehler
Verfasst: Samstag 28. Mai 2011, 23:18
von UnSpeed
mutetella hat geschrieben:UnSpeed hat geschrieben:Da liegt übrigens einer der Unterschiede zu Java
Meines Halbwissens nach gilt das bei Java aber nur für statische Variablen, die es in dieser Form bei Python nicht gibt. Alle anderen Variablen sind ebenfalls sehr wohl an den Namensraum ihrer Deklaration gebunden.
mutetella
Das ist teilweise richtig

In Java gibt es immer eine so genannte
Klasse, diese
Klasse ist sozusagen die Hülle eines Objektes.
Werden nun Variablen in dieser
Klasse deklariert beispielsweise so:
so sind sie auch in alles Methoden dieses Objektes verfügbar.
Nicht jedoch, will man sie aus einer Methode eines anderen Objektes aufrufen, dafür muss sie in der Tat static (statisch) sein
Aber hier gehts ja nicht um Java, deshalb bin ich jetzt mal still
Edit:
BlackJack hat mich freundlicher Weise darauf aufmerksam gemacht, dass das, was ich Konstruktor nannte, natürlich
nicht der Konstruktor, sondern die Klasse ist.
(Geistige Umnachtung

)
Deshalb habe ich 'Konstruktor' in
Klasse geändert.
Vielen Dank an dieser Stelle

Re: Python Variablenfehler
Verfasst: Sonntag 29. Mai 2011, 00:42
von BlackJack
@UnSpeed: Das ist jetzt das erste mal das ich *das* bei Java jemanden den Konstruktor nennen sehe. Das würde ich eher die Deklaration der Exemplarvariablen nennen. Denn die Variablen die man in einem Konstruktor deklariert sind auch bei Java nur innerhalb des Konstruktors sichtbar, wie bei jeder anderen Methode auch.
Code: Alles auswählen
class Test {
int a = 42;
Test() {
int b = 23; // Deklaration im Konstrukor -- nicht ausserhalb sichtbar.
}
}
Auch wenn Du weisst was Rekursion ist — in Java wäre es ebenfalls keine gute Idee sie auf diese Weise zu verwenden. Denn auch Java garantiert keine Optimierung von Endrekursion und würde da *sehr* wahrscheinlich irgendwann mit einem übergelaufenen Aufrufstapel das Programm abbrechen.
Re: Python Variablenfehler
Verfasst: Sonntag 29. Mai 2011, 05:53
von Hyperion
mutetella hat geschrieben:
Code: Alles auswählen
#entweder
eingabe = str(raw_input('Diese Eingabe wird klein: ')).lower()
#oder
eingabe = str(raw_input('Diese Eingabe wird GROSS: ')).upper()
@mutetella: `raw_input` liefert Dir immer einen String zurück - der Aufruf von `str` ist also überflüssig.
Re: Python Variablenfehler
Verfasst: Sonntag 29. Mai 2011, 09:03
von mutetella
@Hyperion:
Ich hatte gehofft, dass das niemand mehr bemerkt...

Re: Python Variablenfehler
Verfasst: Sonntag 29. Mai 2011, 09:32
von UnSpeed
@ Blackjack:
Sicher, du hast recht --> geändert

Re: Python Variablenfehler
Verfasst: Sonntag 29. Mai 2011, 21:51
von mutetella
Zur Übung für mich und auch, weil ich mein Kalenderprogramm heute nicht mehr sehen konnte

habe ich ein wenig herumgespielt, die Eingabeschleife etwas entzerrt und das, was da IMHO nicht unbedingt hineingehört, ausgelagert:
Code: Alles auswählen
import random
LEVEL = {'L': 1, 'M': 5, 'S': 10}
def menu(level=5):
while True:
choice = make_choice(
'Hauptmenu',
'(N)eues Spiel - (L)evelauswahl - (A)nleitung - (E)nde',
'NLAE', False)
if choice == 'N':
#Hier beginnt ein neues Spiel
gamestart(level)
elif choice == 'L':
#Hier kommt die Levelauswahl
choice = make_choice(
'Levelauswahl',
'(L)eicht - (M)ittel - (S)chwer',
'LMS')
if choice != 'X':
level = LEVEL[choice]
elif choice == 'A':
#Hier kommt die Anleitung
manual()
elif choice == 'E':
#Hier wird das Spiel beendet
break
def make_choice(label, text, valid, cancel=True):
if cancel:
prompt = '|Ihre Auswahl oder \'X\' zum Abbrechen > '
valid = valid + 'X'
else:
prompt = '|Ihre Auswahl > '
choice = ''
while True:
print '|{0}'.format(label)
print '|{0}'.format('-'*len(text))
print '|{0}'.format(text)
choice = raw_input(prompt).upper()
print
if choice in valid:
return choice
print '>>>> FEHLERHAFTE EINGABE <<<<'
print 'Bitte treffen Sie Ihre Auswahl aus'
print '{0:^34}'.format(valid)
def gamestart(level):
number = random.randint(0, level*10)
print 'Level {0}: {1}'.format(level, number)
def manual():
print 'So oder so...'
if __name__ == '__main__':
menu()
mutetella
Re: Python Variablenfehler
Verfasst: Montag 30. Mai 2011, 13:09
von EyDu
UnSpeed hat geschrieben:In Java gibt es immer eine so genannte
Klasse, diese
Klasse ist sozusagen die Hülle eines Objektes.
Werden nun Variablen in dieser
Klasse deklariert beispielsweise so:
so sind sie auch in alles Methoden dieses Objektes verfügbar.
Nicht jedoch, will man sie aus einer Methode eines anderen Objektes aufrufen, dafür muss sie in der Tat static (statisch) sein

Du meinst sicher public und nicht static
