Verständnisproblem mit Modul und .lower

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.
Sssnake
User
Beiträge: 10
Registriert: Donnerstag 29. Oktober 2020, 18:30

Ahoi liebe Leute!

Ich fange gerade nach einem Buch an zu lernen und habe da zwei Fragen die ich aus dem Buch heraus nicht beantwortet bekomme.

Die Zeile

Code: Alles auswählen

unbek_buchst = aktu_verdeckt(raten, geheim_wort, verdeckt_wort, unbek_buchst)
habe ich so lange verstanden, bis irgendwann nachträglich vorne und hinten "unbek_buchst" hinzugefügt wurde. Kann mir wer erklären wieso man ein Modul jetzt mit einer Variablen gleichsetzt? Und am Anfang vom Code ist der letzte Parameter gar nicht "unbek_buchst", also es sind nur 3 und nicht 4. Spießt sich das nicht?

Die zweite Frage betrifft die Groß-/Kleinschreibung. Wenn das gesuchte Wort "Pizza" ist und ich ein kleines "p" eingebe, ist die Antwort natürlich falsch. Ich habe versucht ".lower" an alle möglichen Stellen hinzuzufügen, aber es klappt einfach nicht. Was übersehe ich?

Code: Alles auswählen

import random

leben = 7
wörter = ['Pizza', 'Braut', 'Tante', 'Sorge', 'Otter', 'Pferd']
geheim_wort = random.choice(wörter)
verdeckt_wort = list('?????')
herz = u'\u2764'
wort_richtig_geraten = False
unbek_buchst = len(geheim_wort)


def aktu_verdeckt(buchstabe_geraten, geheim_wort, verdeckt_wort):
    index = 0 # Startet mit der Prüfung bei Position null
    while index < len(geheim_wort): # ohne das prüft das Modul ewig lang weiter
        if buchstabe_geraten == geheim_wort[index]: # [index] sorgt dafür, dass das Programm die korrekte Position findet
            verdeckt_wort[index] = buchstabe_geraten
            unbek_buchst = unbek_buchst - 1
        index = index + 1
    return unbek_buchst # Gibt die Anzahl an die Variable zurück, damit man sie nicht extra wo speichern muss

    
while leben > 0:
    print(verdeckt_wort)
    print('Verbleibende Leben: ' + herz * leben)
    raten = input('Rate einen Buchstaben oder das Wort: ')

    if raten == geheim_wort:
          wort_richtig_geraten = True
          break
          
    if raten in geheim_wort:
        unbek_buchst = aktu_verdeckt(raten, geheim_wort, verdeckt_wort, unbek_buchst)
    else:
        print('Falsch. Ein Leben weniger.')
        leben = leben - 1

    if unbek_buchst == 0:
        wort_richtig_geraten = True
        break

if wort_richtig_geraten: # wenn nichts dabei steht ist es automatisch True
    print('Du hast gewonnen! Das Wort war ' + geheim_wort)
else:
    print('Leider verloren! Das Wort war ' + geheim_wort)
    
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wo wird da „ein Modul mit einer Variable gleichgesetzt“? Der Aufruf funktioniert so natürlich nicht wegen der Anzahl der Argumente. Da fehlt ein Argument bei der Definition der Funktion.

Was ansonsten negativ auffällt sich die komischen Namen und das da Code und Variablen auf Modulebene stehen wo sie nicht hingehören.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

Was ist ein `aktu`? Oder was bedeutet `unbek`? Unbekömmlich, unbekleidet, ...? Benutze keine Abkürzungen, das führt nur zu Verwirrung und macht das Lesen und damit das Verstehen schwierig.
Variablen sollten dann definiert werden, wenn sie auch gebraucht werden und nicht irgendwo am Anfang der Datei. Der ganze Code sollte auch in Funktionen wandern.
Die Fragezeichen sollten nicht fix im Code stehen, sondern anhand der Länge des geheim_wort ermittelt werden.
Die while-Schleife in aktu_verdeckt ist eigentlich eine for-Schleife.

Code: Alles auswählen

import random

def aufdecken(buchstabe_geraten, geheim_wort, verdeckt_wort, fehlende_buchstaben):
    for index in range(len(geheim_wort)):
        if buchstabe_geraten == geheim_wort[index]:
            verdeckt_wort[index] = buchstabe_geraten
            fehlende_buchstaben -= 1
    return fehlende_buchstaben

def wort_raten(geheim_wort):
    herz = u'\u2764'
    verdeckt_wort = ['?'] * len(geheim_wort)
    fehlende_buchstaben = len(geheim_wort)
    leben = 7
    while leben > 0:
        print(verdeckt_wort)
        print(f'Verbleibende Leben: {herz * leben}')
        raten = input('Rate einen Buchstaben oder das Wort: ')
        if raten == geheim_wort:
            return True
        elif raten in geheim_wort:
            fehlende_buchstaben = aufdecken(raten, geheim_wort, verdeckt_wort, fehlende_buchstaben)
            if fehlende_buchstaben == 0:
                return True
        else:
            print('Falsch. Ein Leben weniger.')
            leben -= 1
    return False

def main():
    wörter = ['Pizza', 'Braut', 'Tante', 'Sorge', 'Otter', 'Pferd']
    geheim_wort = random.choice(wörter)
    wort_richtig_geraten = wort_raten(geheim_wort) 
    if wort_richtig_geraten:
        print(f'Du hast gewonnen! Das Wort war {geheim_wort}')
    else:
        print(f'Leider verloren! Das Wort war {geheim_wort}')

if __name__ == '__main__':
    main()
Jetzt ist noch schlecht, dass Du eine Funktion hast, die eine Liste verändert. Besser ist es, neue Listen zu erzeugen. `fehlende_buchstaben` ist eigentlich unnötig, weil man genauso prüfen könnte, ob noch ein Platzhalter in verdeckt_wort ist.

Code: Alles auswählen

import random

def aufdecken(buchstabe_geraten, geheim_wort, verdeckt_wort):
    return [
        geheim_zeichen if geheim_zeichen == buchstabe_geraten else verdeckt_zeichen
        for geheim_zeichen, verdeckt_zeichen in zip(geheim_wort, verdeckt_wort)
    ]

def wort_raten(geheim_wort):
    herz = u'\u2764'
    verdeckt_wort = ['?'] * len(geheim_wort)
    leben = 7
    while leben > 0:
        print(' '.join(verdeckt_wort))
        print(f'Verbleibende Leben: {herz * leben}')
        raten = input('Rate einen Buchstaben oder das Wort: ')
        if raten == geheim_wort:
            return True
        elif raten in geheim_wort:
            verdeckt_wort = aufdecken(raten, geheim_wort, verdeckt_wort)
            if '?' not in verdeckt_wort:
                return True
        else:
            print('Falsch. Ein Leben weniger.')
            leben -= 1
    return False

def main():
    wörter = ['Pizza', 'Braut', 'Tante', 'Sorge', 'Otter', 'Pferd']
    geheim_wort = random.choice(wörter)
    wort_richtig_geraten = wort_raten(geheim_wort) 
    if wort_richtig_geraten:
        print(f'Du hast gewonnen! Das Wort war {geheim_wort}')
    else:
        print(f'Leider verloren! Das Wort war {geheim_wort}')

if __name__ == '__main__':
    main()
Sssnake
User
Beiträge: 10
Registriert: Donnerstag 29. Oktober 2020, 18:30

@_blackjack_ Stimmt, habe doch glatt überlesen, dass der Parameter auch ins Modul gehört. Die Abkürzungen (kompletter Code lt. Buch) fand ich eigentlich ganz verständlich, aber ich weiß was du meinst.

@Sirius3: Danke für die Vorschläge, aber das ist mir für den Anfang dann doch etwas zu komplex. Ich verstehe schon, dass der Code laut Buch sicher noch einfacher geht, aber für den Anfang muss ich erstmal nur grundsätzlich verstehen lernen. Der Feinschliff kommt später.

Grundsätzlich wurde meine erste Frage nun geklärt, aber es wäre immer noch offen wie ich das mit der Groß-/Kleinschreibung löse. Ich habe wie gesagt ".lower" in diversen Zeilen eingebaut, aber entweder hat das nichts gebracht oder zu Fehlermeldungen geführt.
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

An welcher Stelle werden Buchstaben miteinander verglichen? Dort muß man dann Kleinbuchstaben miteinander vergleichen.
Benutzeravatar
snafu
User
Beiträge: 6870
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Sssnake hat geschrieben: Freitag 30. Oktober 2020, 06:21 Die Abkürzungen (kompletter Code lt. Buch) fand ich eigentlich ganz verständlich, aber ich weiß was du meinst.
Das Ding ist, dass zwar du aus dem aktuellen Kontext mit den Abkürzungen klar kommst, aber jemand anders, der dir helfen soll, womöglich nicht. Und schlimmstenfalls musst du nach ein paar Monaten, wenn du mal wieder in den Code schaust, auch erstmal rätseln, was gemeint war. Das erspart man sich halt durch mögliches Ausschreiben aller Namen bzw der Beschränkung auf gängige Abkürzungen. Wobei das natürlich wieder Ansichtssache ist, was "gängig" sein soll. Ich schreibe z.B. num_items oder max_values, weil ich das für gängig halte. Aber es gibt bestimmt Leute, die lieber number_of_items und maximal_values nutzen würden.
Sssnake
User
Beiträge: 10
Registriert: Donnerstag 29. Oktober 2020, 18:30

Sirius3 hat geschrieben: Freitag 30. Oktober 2020, 08:41 An welcher Stelle werden Buchstaben miteinander verglichen? Dort muß man dann Kleinbuchstaben miteinander vergleichen.
Schon. Daher habe ich ja die lower Funktion genutzt. Das Problem ist halt, dass es nie funktioniert hat. Für die Prüfung selbst kann ich die Buchstaben mit der Funktion ja klein machen, aber mein Programm schreibt es einfach nicht. Ich MUSS den Anfangsbuchstaben derzeit groß schreiben beim raten.
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sssnake: zeig den Code, den Du versucht hast und die Fehlermeldung, falls es eine gibt.
Sssnake
User
Beiträge: 10
Registriert: Donnerstag 29. Oktober 2020, 18:30

Code: Alles auswählen

while index < len(geheim_wort): 
        if buchstabe_geraten.lower == geheim_wort[index].lower: 
            verdeckt_wort[index] = buchstabe_geraten
So klappts nicht. Und wenn ich das .lower auch in die untere Zeile einsetze kommt das hier:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Users\NAME\Desktop\Python\15. Ratespiel.py", line 32, in <module>
    unbek_buchst = aktu_verdeckt(raten, geheim_wort, verdeckt_wort, unbek_buchst)
  File "C:\Users\NAME\Desktop\Python\15. Ratespiel.py", line 16, in aktu_verdeckt
    verdeckt_wort[index].lower = buchstabe_geraten.lower
AttributeError: 'str' object attribute 'lower' is read-only
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

"So klapps nicht" ist viel weniger Aussagekräftig als die Fehlermeldung. Also immer Code und die dazugehörige Fehlermeldung zeigen. Hier passen Code und Fehlermeldung nicht zusammen.

lower ist eine Methode, die Zeichenketten haben.
Um eine Methode aufzurufen, musst du ihr in Klammern Parameter übergeben. Die Parameterliste kann auch leer sein.
.lower -> ein Vereis auf die Methode.
.lower() -> Der Aufruf der Methode.

Deshalb ist es wichtig, Code zu zeigen.
Sssnake
User
Beiträge: 10
Registriert: Donnerstag 29. Oktober 2020, 18:30

Ich dachte es wäre klar geschrieben, sorry. Das "so klappts nicht" bezog sich auf den oberen Code. Ich wollte den selben Code nicht nochmal posten nur wegen einer einzelnen Änderung. Sorry.

Die Fehlermeldung kommt bei diesem Code:

Code: Alles auswählen

while index < len(geheim_wort): 
        if buchstabe_geraten.lower == geheim_wort[index].lower: 
            verdeckt_wort[index].lower = buchstabe_geraten.lower
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

lower ist eine Methode, und muss aufgerufen werden. Mit

meinstring.lower()

Man beachte die Klammern.

Und du versuchst einer Methode etwas zu zuweisen. Das geht nicht. So geht das:

verdeckt_wort[index] = buchstabe_geraten.lower()

Auch hier wieder: Aufruf vergessen.
Sssnake
User
Beiträge: 10
Registriert: Donnerstag 29. Oktober 2020, 18:30

Danke, damit bin ich einen Schritt weiter und bekomme die Fehlermeldung weg.

Aber egal wo ich das eintrage, das Problem bleibt.

Mit

Code: Alles auswählen

if buchstabe_geraten.lower() == geheim_wort[index].lower()
werden ja erstmal nur die Eingabe und das zu prüfende Wort klein gemacht. Soweit so gut. Aber das Programm erkennt die EIngabe dann nicht als richtig an und der Anfangsbuchstabe wird damit auch nicht aufgedeckt.

Wenn ich

Code: Alles auswählen

verdeckt_wort[index] = buchstabe_geraten.upper()
eingebe wird aber JEDER Buchstabe groß, was falsch ist.

Geplant ist, dass wenn zB "Pizza" gesucht wird, ich auch ein kleines "p" eingeben kann, es dann als richtig anerkannt wird und korrekt (also groß) aufgedeckt wird (P ? ? ? ? ?).
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Du das so willst, mußt es so programmieren. Gehe Funktion `aufdecken` Schritt für Schritt mit verschiedenen Beispielen durch und schaue was passiert. Wie wird an welchen Stellen mit großen oder kleinen Buchstaben umgegangen?
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Sssnake hat geschrieben: Freitag 30. Oktober 2020, 06:21Stimmt, habe doch glatt überlesen, dass der Parameter auch ins Modul gehört. […]
Welches Modul? Module haben keine Parameter. Kann es sein, dass Du hier Funktionen als Module bezeichnest?
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sssnake
User
Beiträge: 10
Registriert: Donnerstag 29. Oktober 2020, 18:30

@_blackjack_: Ja, sorry, Funktionen. Hat sich falsch abgespeichert. ^^

@Sirius3: Das habe ich getan und komme nicht auf die Lösung. Andernfalls würde ich hier nicht um Hilfe ansuchen.

Code: Alles auswählen

if buchstabe_geraten.lower() == geheim_wort[index].lower(): 
            verdeckt_wort[index] = buchstabe_geraten
buchstabe_geraten.lower() macht meine EIngabe klein.

== geheim_wort[index].lower() vergleicht die klein gemachte EIngabe mit dem Buchstaben im geheim_wort an der Position "index" und das ebenfalls in kleiner Form. Somit müsste aber auch der erste Buchstabe vom Wort "Pizza" für die Prüfung klein gemacht sein.

verdeckt_wort[index] = buchstabe_geraten ersetzt dann das Fragezeichen an der entsprechenden Position mit dem geratenen Buchstaben. Die .lower() Sache betrifft - so denke ich - aber nur die Prüfung, also die eine Zeile darüber. Demnach müsste dann der verdeckte Buchstabe 1:1 mit meiner Eingabe ersetzt werden, je nachdem ob groß oder klein. Wenn ich den Buchstaben klein eingebe geht zwar die Prüfung durch (s. voriger Gedankengang), aber wird auch dann klein geschrieben. Da dies aber nicht der Fall ist, muss schon die Prüfung falsch sein. Und genau hier komm ich nicht weiter.
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sssnake: Bei dem Code den Du da zeigst und im Grunde ja auch so beschreibst, wird die Eingabe 1:1 übernommen. Wenn Du ein kleines 'p' bei Pizza eingibst, dann wird auch ein kleines 'p' aufgedeckt. Wenn Du da den Buchstaben in der Schreibweise haben willst wie er im geheimen Wort gespeichert ist, dann musst Du halt auch den Buchstaben aus dem geheimen Wort für das aufdecken verwenden, und nicht den Buchstaben den Du eingegeben hast.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sssnake
User
Beiträge: 10
Registriert: Donnerstag 29. Oktober 2020, 18:30

Nach der Logik müsste der Code dann ja

Code: Alles auswählen

verdeckt_wort[index] = geheim_wort[index]
heißen, aber das klappt auch nicht.
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sssnake: Ja so müsste das dann heissen. Was klappt daran nicht?
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sssnake
User
Beiträge: 10
Registriert: Donnerstag 29. Oktober 2020, 18:30

Das kommt raus:

Code: Alles auswählen

['?', '?', '?', '?', '?']
Verbleibende Leben: ❤❤❤❤❤❤❤
Rate einen Buchstaben oder das Wort: p
Falsch. Ein Leben weniger.
['?', '?', '?', '?', '?']
Verbleibende Leben: ❤❤❤❤❤❤
Rate einen Buchstaben oder das Wort: P
['P', '?', '?', '?', '?']
Verbleibende Leben: ❤❤❤❤❤❤
Rate einen Buchstaben oder das Wort: 

Hier nochmal der gesamte Code:

Code: Alles auswählen

import random

leben = 7
wörter = ['Pizza', 'Praut', 'Pante', 'Porge', 'Ptter', 'Pferd']
geheim_wort = random.choice(wörter)
verdeckt_wort = list('?????')
herz = u'\u2764'
wort_richtig_geraten = False
unbek_buchst = len(geheim_wort)


def aktu_verdeckt(buchstabe_geraten, geheim_wort, verdeckt_wort, unbek_buchst):
    index = 0 # Startet mit der Prüfung bei Position null
    while index < len(geheim_wort): # ohne das prüft das Modul ewig lang weiter
        if buchstabe_geraten.lower() == geheim_wort[index].lower(): # [index] sorgt dafür, dass das Programm die korrekte Position findet
            verdeckt_wort[index] = geheim_wort[index]
            unbek_buchst = unbek_buchst - 1
        index = index + 1
    return unbek_buchst # Gibt die Anzahl an die Variable zurück, damit man sie nicht extra wo speichern muss

    
while leben > 0:
    print(verdeckt_wort)
    print('Verbleibende Leben: ' + herz * leben)
    raten = input('Rate einen Buchstaben oder das Wort: ')

    if raten == geheim_wort:
          wort_richtig_geraten = True
          break
          
    if raten in geheim_wort:
        unbek_buchst = aktu_verdeckt(raten, geheim_wort, verdeckt_wort, unbek_buchst)
    else:
        print('Falsch. Ein Leben weniger.')
        leben = leben - 1

    if unbek_buchst == 0:
        wort_richtig_geraten = True
        break

if wort_richtig_geraten: # wenn nichts dabei steht ist es automatisch True
    print('Du hast gewonnen! Das Wort war ' + geheim_wort)
else:
    print('Leider verloren! Das Wort war ' + geheim_wort)
Antworten