ubuntuusers.de

TypeError: 'str' object is not callable (Python)

Status: Gelöst | Ubuntu-Version: Ubuntu
Antworten |

nexonic

Anmeldungsdatum:
23. Januar 2008

Beiträge: 952

Hallo,

da ich zurzeit Python lerne, bin ich dabei, zur Übung ein "Wer Wird Millionär" Spiel zu programmieren.
Bisher habe ich nur ein reines "Frage - Antwort - Du hast x Euro gewonnen / Leider Falsch" Spiel.
Also so: http://immanuel.sciency.net/PY-Scripte/WWM-0.1.py

Jetzt bin ich dabei eine "Aufhörfunktion" einzubauen, also, dass der Spieler bei einer Frage, die ihm zu schwierig ist, aufhören kann
und den zuvor gewonnenen Betrag bekommt.
Bisher bin ich so weit, dass man nach dem Stellen der Fragen, entweder 'a-d' für die Antworten eingibt oder 's' drückt.
Wenn man 's' drückt, wird man gefragt, ob man wirklich aufhören möchte.

So, wenn man dann 'n' für nein drückt, wird die Frage, also die eigentliche Frage, nochmal gestellt.
Wenn man dann wieder 's' drückt kommt folgende Meldung:

Traceback (most recent call last):
  File "WWM-Neu.py", line 269, in <module>
    frage_stellen(50,0)
  File "WWM-Neu.py", line 188, in frage_stellen
    stop(stop_wert21,wert21,frage_nummer21)	
  File "WWM-Neu.py", line 246, in stop
    stop(stop_wert21,wert21,frage_nummer21)		
TypeError: 'str' object is not callable

Und irgendwie kann ich sie nicht nachvollziehen, wenn überhaupt verstehen.
Hier der Code dazu:
http://immanuel.sciency.net/PY-Scripte/WWM-Neu.py

Ich hoffe mir kann jemand weiterhelfen.

Gruss
N3X0NIC

freze

Anmeldungsdatum:
19. Januar 2006

Beiträge: 87

Ich werde beim druecken von "s" nicht gefragt, ob ich aufhoeren moechte. Kann etwas entsprechendes auch nicht im Code sehen.
Darum kann ich den Fehler nicht nachvollziehen. Sicher, dass du die aktuelle Version hochgeladen hast?

MrKanister

Anmeldungsdatum:
13. Oktober 2007

Beiträge: 2105

Woran es jetzt genau liegt weiß ich nicht (dazu wäre eventuell ein Minimal-Beispiel, das den Fehler reproduziert, gut), aber die Rekursion, die du eingebaut hast, ist nicht gut.

def funktion1():
   if blabla:
       fuktion1()


Bau lieber eine Funktion mit ordentlichem Rückgabewert in Form eines "return". 😉

Gruß Martin

nexonic

(Themenstarter)

Anmeldungsdatum:
23. Januar 2008

Beiträge: 952

Mr. Kanister hat geschrieben:

Woran es jetzt genau liegt weiß ich nicht (dazu wäre eventuell ein Minimal-Beispiel, das den Fehler reproduziert, gut), aber die Rekursion, die du eingebaut hast, ist nicht gut.

def funktion1():
   if blabla:
       fuktion1()


Bau lieber eine Funktion mit ordentlichem Rückgabewert in Form eines "return". 😉

Gruß Martin

Öhm, danke für den Tipp ☺
Aber wie stelle ich das an?
Ich habe jetzt in der Funktion "stop" solche Sachen versucht wie:

if eingabe == 's':
			return(stop_wert2,wert2,frage_nummer2)
			stop(stop_wert2,wert2,frage_nummer2)

Aber dann macht er mit der nächsten Frage weiter, ohne zur stop Funktion zurückzukehren 🙄

Gruss

MrKanister

Anmeldungsdatum:
13. Oktober 2007

Beiträge: 2105

Alles was in einer Funktion nach einem ausgeführten "return" steht, wird nicht mehr ausgeführt, weil die Funktion den Rückgabewert an den Aufrufer zurück gibt und sich beendet.

Denk dir eine Funktion für das Einlesen der Benutzereingabe (Das ist jetzt kein korrekter Python Code, sondern viel mehr eine Ansammlung von Gedanken 😉)

def abfrage(eingabe):
    wenn eingabe ist "a", "b", "c" oder "d":
        return True
    wenn eingabe ist "s":
        # sind sie sicher?
        if str(raw_input("Sind sie sicher") == "n":
            return True
        else
            return False


In deinem EIgentlichen Quellcode steht dann zB:

...
eingabe = str(war_input("a, b, c oder d? "))
if abfrage(eingabe) == False:
    # Ende
else
    # Spiel geht weiter...testen ob USer hat richtig geraten
    if eingabe == "a":
        print "wow, du hast gewonnen ;)"

Ich hoffe das Beispiel verdeutlicht in etwa was ich meine 😉

Gruß Martin

nexonic

(Themenstarter)

Anmeldungsdatum:
23. Januar 2008

Beiträge: 952

Cool Danke ☺

Mit ein wenig Ausweitung deiner "Gedanken" hab ich es zustande gebracht 😀

Die Version 0.2 gibts hier:
http://immanuel.xail.net/program/py_scripts/WWM-0.2.zip

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Du musst den Quellcode nicht zippen 😮

Ungezipt lässt er sich fixer anschaun.

nexonic

(Themenstarter)

Anmeldungsdatum:
23. Januar 2008

Beiträge: 952

Ist aber noch eine README dabei, deswegen 😀 😛

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

function zipload() {
    FILE==(wget -q -O - $(xclip -o))
    unzip -p $FILE | vim -;
    rm $FILE


So. Problem gelöst 😉

Außerdem mal eine Anregung:

# Fragstellfunktion aufrufen
for value, stop in\
    [(50,0)
    ,(100,50)
    ,(200,100)
    ,(300,200)
    ,(500,300)
    ,(1000,500)
    ,(2000,1000)
    ,(4000,2000)
    ,(8000,4000)
    ,(16000,8000)
    ,(32000,16000)
    ,(64000,32000)
    ,(125000,64000)
    ,(500000,125000)
    ,(1000000,500000)]:
    frage_stellen(value, stop)
    risiko += 1

Es ist übrigens unschön, risiko einfach so zu inkrementieren.
Bau halt eine Klasse Quiz mit nem Attribut risiko, das ist hübscher.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4694

Wohnort: Berlin

So besonders toll ist es immer noch nicht. An der Form würde ich erst einmal bemängeln, dass viele Zeilen länger als 80 Zeichen sind und Tabs zum Einrücken verwendet wurden. Letzteres wird früher oder später zu Problemen führen wenn man nicht aufpasst und Tabs und Leerzeichen mischt und dadurch Fehler mit der Einrückung auftreten, die man mit blossem Auge nicht sieht.

Auf Modulebene sollten nur Konstanten, Funktionen, und Klassen existieren. Globale Variablen sind "böse", weil sie das verstehen des Programms erschweren.

Die "Namensgruppen" stop_wert, stop_wert2, stop_wert21, usw. sind unverständlich. Was sollen diese Zahlen in den Namen bedeuten!? Und letztendlich werden die bis auf risiko im ganzen Programm dann überhaupt nicht verwendet.

Die einzelnen Fragen könnte man noch weiter strukturieren. Eine Frage, die möglichen Antworten und die richtige Antwort sind verschiedene Informationen, die hier in einer Liste zusammen geworfen werden. Die möglichen Antworten könnte man in eine Liste oder ein Tupel stecken. Dabei sollte man die Buchstaben am Anfang weglassen, die lassen sich auch vom Programm generieren. Sind ja immer die selben.

Die Funktion frage_stellen() ist für meinen Geschmack zu gross und zu kompliziert. Das kann man sicher aufteilen, insbesondere die inneren Funktionen könnte man heraus ziehen.

Das Ermitteln einer zufälligen Frage ist unnötig kompliziert. count an eine 0 zu binden ist völlig sinnlos, wenn man den Namen gleich in der nächsten Zeile an etwas anderes bindet.

Die folgende ``if``/``else``-Abfrage ist überflüssig. Wenn count gleich 1 ist, dann wird eben eine Zufallszahl zwischen 1 und 1 gewählt. Schadet ja nicht weiter, da kommt eben immer 1 bei heraus.

Ebenfalls umständlich ist es eine Zufallszahl zwischen 1 und ``count+1`` zu wählen, um dann vom Ergebnis 1 ab zu ziehen. Da hätte man die Zufallszahl auch gleich zwischen 0 und count erzeugen lassen können.

Aber letztendlich sind die ganzen Zeilen, count, und frage_nummer überflüssig, weil man ganz einfach mit ``random.choice(fragen[wert])`` eine Frage auswählen kann. In einer Zeile, und dann hat man auch gleich die Struktur mit der Frage selbst und muss im weiteren Verlauf nicht mehr so umständlich verschachtelt indexiert auf die einzelnen Werte zu greifen.

Wenn man eine Bedingung in einem ``if`` hat und die beiden Zweige nur entweder True oder False zurückgeben, kann man sich das ``if`` sparen und gleich aus dem Ergebnis der Bedingung den Rückgabewert bilden. Also statt:

                if stop == 'n':
                    return True
                else:
                    return False

einfach:

                return stop == 'n'

In einer Bedingung braucht man einen Wahrheitswert nicht noch einmal explizit mit einem literalen Wahrheitswert vergleichen. Also statt ``if foo() == True:`` einfach nur ``if foo():``.

Magische Konstanten sollten vermieden werden. Zum Beispiel der Test von risiko auf 14. Die Information, wie viele Stufen es gibt, steckt schon in der Datenstruktur fragen. Ähnliches gilt für die "Rückfall-Gewinnstufen". Die sollten entweder als benannte Konstanten festgelegt werden, oder als Datenstruktur, zum Beispiel eine Liste mit den Stufen auf die man zurück fallen kann.

Am Ende des Quelltextes wäre eine Schleife angebracht. Auch hier sind wieder magische Konstanten, die man sich aus fragen holen kann. Dort stehen die Beträge schliesslich schon einmal.

Man könnte noch die Beträge aus der fragen-Struktur ziehen und diese zu einer Liste machen wo der Index die Stufe angibt. Dann bräuchte man auch nicht die zwei Argumente bei der frage_stellen()-Funktion sondern nur die aktuelle Stufe.

nexonic

(Themenstarter)

Anmeldungsdatum:
23. Januar 2008

Beiträge: 952

@Marc 'BlackJack' Rintsch:
Danke für die "Tipps" erstmal ☺
Das alles war für mich ja schon fast eine Überforderung 😬 , aber ich denke ich konnte doch die Meisten deiner "Wünsche" "erfüllen" 😉

Marc 'BlackJack' Rintsch hat geschrieben:

In einer Bedingung braucht man einen Wahrheitswert nicht noch einmal explizit mit einem literalen Wahrheitswert vergleichen. Also statt ``if foo() == True:`` einfach nur ``if foo():``.

ein ``if blabla() == True:`` hatte ich garnicht 😉

Marc 'BlackJack' Rintsch hat geschrieben:

...würde ich erst einmal bemängeln, dass viele Zeilen länger als 80 Zeichen sind...

Was ist daran schlimm?

Marc 'BlackJack' Rintsch hat geschrieben:

Die "Namensgruppen" stop_wert, stop_wert2, stop_wert21, usw. sind unverständlich. Was sollen diese Zahlen in den Namen bedeuten!?

Die waren noch von meinem ersten Versuch im ersten Post, hatte ich vergessen zu löschen 😳 ☺

Marc 'BlackJack' Rintsch hat geschrieben:

Die einzelnen Fragen könnte man noch weiter strukturieren. Eine Frage, die möglichen Antworten und die richtige Antwort sind verschiedene Informationen, die hier in einer Liste zusammen geworfen werden. Die möglichen Antworten könnte man in eine Liste oder ein Tupel stecken. Dabei sollte man die Buchstaben am Anfang weglassen, die lassen sich auch vom Programm generieren. Sind ja immer die selben.

Was bringt das? Die Struktur wie sie ist geht doch ?!?

Marc 'BlackJack' Rintsch hat geschrieben:

Magische Konstanten

Was ist das?

Marc 'BlackJack' Rintsch hat geschrieben:

Auch hier sind wieder magische Konstanten, die man sich aus fragen holen kann. Dort stehen die Beträge schliesslich schon einmal.
...
Man könnte noch die Beträge aus der fragen-Struktur ziehen und diese zu einer Liste machen wo der Index die Stufe angibt. Dann bräuchte man auch nicht die zwei Argumente bei der frage_stellen()-Funktion sondern nur die aktuelle Stufe.

Wie hol ich mir denn die 'key' werte aus 'fragen' ?
Und was würde es bringen, nur EIN Argument in frage_stellen() zu haben?

Marc 'BlackJack' Rintsch hat geschrieben:

Am Ende des Quelltextes wäre eine Schleife angebracht.

Was für eine Schleife und wofür?

Datei im Anhang.

Gruss

WWM-Neu.py (9.0 KiB)
Download WWM-Neu.py

MrKanister

Anmeldungsdatum:
13. Oktober 2007

Beiträge: 2105

N3X0NIC hat geschrieben:

Marc 'BlackJack' Rintsch hat geschrieben:

...würde ich erst einmal bemängeln, dass viele Zeilen länger als 80 Zeichen sind...

Was ist daran schlimm?

Schau dir mal das PEP8 - Style Guide zu Python an. Danach weißt du warum 😉

N3X0NIC hat geschrieben:

Marc 'BlackJack' Rintsch hat geschrieben:

Die einzelnen Fragen könnte man noch weiter strukturieren. Eine Frage, die möglichen Antworten und die richtige Antwort sind verschiedene Informationen, die hier in einer Liste zusammen geworfen werden. Die möglichen Antworten könnte man in eine Liste oder ein Tupel stecken. Dabei sollte man die Buchstaben am Anfang weglassen, die lassen sich auch vom Programm generieren. Sind ja immer die selben.

Was bringt das? Die Struktur wie sie ist geht doch ?!?

Ob eine Struktur nur einfach funktioniert, oder ob sie auch flexibel und leserlich strukturiert ist, ist schon ein Unterschied.

N3X0NIC hat geschrieben:

Marc 'BlackJack' Rintsch hat geschrieben:

Auch hier sind wieder magische Konstanten, die man sich aus fragen holen kann. Dort stehen die Beträge schliesslich schon einmal.
...
Man könnte noch die Beträge aus der fragen-Struktur ziehen und diese zu einer Liste machen wo der Index die Stufe angibt. Dann bräuchte man auch nicht die zwei Argumente bei der frage_stellen()-Funktion sondern nur die aktuelle Stufe.

Wie hol ich mir denn die 'key' werte aus 'fragen' ?

http://docs.python.org/tut/node7.html#SECTION007500000000000000000

N3X0NIC hat geschrieben:

Marc 'BlackJack' Rintsch hat geschrieben:

Am Ende des Quelltextes wäre eine Schleife angebracht.

Was für eine Schleife und wofür?

Ich glaube er meint eine große

while True:
...


Schleife, die du, wenn das Programm beendet werden soll, einfach abbrichst.

Gruß Martin

Lunar

Anmeldungsdatum:
17. März 2006

Beiträge: 5792

N3X0NIC hat geschrieben:

Marc 'BlackJack' Rintsch hat geschrieben:

...würde ich erst einmal bemängeln, dass viele Zeilen länger als 80 Zeichen sind...

Was ist daran schlimm?

Versuche einfach mal, auf einem 17''-Monitor zwei Codestücke nebeneinander anzeigen zu lassen ...

N3X0NIC hat geschrieben:

Marc 'BlackJack' Rintsch hat geschrieben:

Die einzelnen Fragen könnte man noch weiter strukturieren. Eine Frage, die möglichen Antworten und die richtige Antwort sind verschiedene Informationen, die hier in einer Liste zusammen geworfen werden. Die möglichen Antworten könnte man in eine Liste oder ein Tupel stecken. Dabei sollte man die Buchstaben am Anfang weglassen, die lassen sich auch vom Programm generieren. Sind ja immer die selben.

Was bringt das? Die Struktur wie sie ist geht doch ?!?

Sie ist aber nicht logisch, da Daten mit unterschiedlicher Bedeutung zusammen gefasst werden. Eine Struktur, die als erstes Element die Frage als Zeichenkette, als zweites Element die möglichen Antworten als Zeichenketten in einem Tupel und als drittes Element den index der richtigen Antwort in diesem Tupel enthält, trennt die Daten dagegen nach ihrer Bedeutung, und erleichtert so das Verständnis des Codes.

Noch als Tipp für die Zukunft: "Geht doch" ist kein Qualitätsmerkmal, sondern Vorraussetzung. Ein Programm muss immer "gehen", also seinen Aufgabenzweck erfüllen. Ein gutes Programm ist darüber hinaus noch sauber entworfen, und elegant und logisch programmiert, so dass das Verständis des Codes vereinfacht wird, was wiederrum die Wartbarkeit fördert und Fehler vermeidet.

N3X0NIC hat geschrieben:

Marc 'BlackJack' Rintsch hat geschrieben:

Magische Konstanten

Was ist das?

if foobar == 14:


14 wäre eine magische Konstante. Allgemein ist das eine Konstante, welche eine gewisse Bedeutung besitzt, trotzdem aber nicht als symbolischer Name, sondern als Literal im Code steht. Anders gesagt: Im Beispiel sieht man der 14 nicht an, dass sie für als die Zahl "vierzehn" steht.

snafu1

Avatar von snafu1

Anmeldungsdatum:
5. September 2007

Beiträge: 2133

Wohnort: Gelsenkirchen

Mal so als Anregung:

fragen = ('Wer ist Bundeskanzler?', ['a) Anneliese Ferkel', 'b) Angela Merkel', 
          'c) Agathe Gerkel', 'd) Alice Jerkel'], 'b')
         
frage, antworten, loesung = fragen

print frage

for antwort in antworten:
    print antwort
    
eingabe = raw_input('Wie lautet die richtige Antwort? ')

if eingabe == loesung:
    print 'Richtig!'
else:
    print 'Leider falsch...'

Funktioniert natürlich auch als Dictionary, aber das stell ich dir jetzt nicht alles um... 😉

DasIch

Avatar von DasIch

Anmeldungsdatum:
2. November 2005

Beiträge: 1130

Du kannst mit for..in und range deine letzte Funktion auf 2 Zeilen kürzen und btw. was bezweckst du mit nichts als Variable? Du musst keine Parameter an Funktionen übergeben, wenn du doch das verlangen verspüren solltest später eventuell Modifikationen vorzunehmen, kannst du Standard Werte festlegen.

>>> def foo(bar=0):
...     print bar
... 
>>> foo()
0
>>> foo(1)
1
Antworten |