def beispiel() mit mehreren Variablen

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.
Antworten
Benutzeravatar
MrBrightside
User
Beiträge: 10
Registriert: Dienstag 14. November 2017, 16:01

Hallo zusammen,

Ich habe mich wie empfohlen von Anfang an durch das Tutorial gearbeitet.
Zum Thema Variablen in einer Funktion bin ich auf ein Problem gestoßen wo ich die Quelle nicht verstehe oder erkennen.
Folgendes Szenario.

Ich habe Versucht eine Operation in eine Funktion auszulagern um den Quellcode übersichtlicher zu gestalten. Wenn ich die Operation direkt in den Code schreibe und diesen nicht auslagr, funktioniert auch alles. Sobald ich die Funktion verwende, werden Teile der Operation nicht oder fehlerhaft durchgeführt.

Beispiel am Code:

Code: Alles auswählen

#Funktionen
#--------------------------------------------------------------
def answer_check(answer, points, rights, wrongs):
    if answer == solution:
        print("Correct.")
        points=points+3
        rights=rights+1
    else:
        print("Wrong.")
        points=points-1
        wrongs=wrongs+1
    return points, rights, wrongs

#Programm
#--------------------------------------------------------------
points=0
rights=0
wrongs=0

for question, answer in zip((questions), (answers)):
    print(question)
    answer=" "
    while answer not in ("A", "B", "C"):
        answer=input("Your Answer (A, B, or C):")
    answer_check(answer, points, rights, wrongs)
    print("Points: {}\nCorrect answers: {}\nWrong answers: {}".format(points, rights, wrongs)
Ich hoffe sehr das ich im Tutorial nicht einfach was überlesen habe, ich bin wieder seit heute morgen dran und möglicherweise nicht mehr ganz so aufmerksam. Ich habe allerdings nochmal versucht das Problem selber zu lösen während ich den Beitrag geschrieben habe.

Was mir noch beim Testen aufgefallen ist:
- Wenn ich die Ausgabe in der Funktion hinterlege, werden die korrekt berechneten Werte ausgegeben.
- Allerdings scheint die Funktion immer wieder mit "0"-Werten in den Variablen anzufangen.
- Beim nächsten Schleifendurchlauf wäre als bei der Berechnung "points", "rights" und "wrongs" wieder bei "0" (Abhängig davon was ich bei der
Variablendeklaration angebe.).

Daraus erschliesst sich mir, das lediglich die Rückgabe der Variablen nicht funktioniert. Somit liest die Funktion immer wieder "0" ein, da die Variablen nicht aktualisiert werden und gibt immer "0" aus, da die Rückgabe nicht funktioniert.

Vielen Dank für eure Zeit

Gruß
Flo
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@MrBrightside: Dein Code funktioniert nicht, weil `solution` nirgends definiert ist.

Die Rückgabe der Werte funktioniert, doch Du fängst mit den Rückgabewerten von `answer_check` nichts an. In Zeile 20 sind zwei Klammernpaare zu viel und die while-Schleife sollte eine while-True-Schleife sein.

Code: Alles auswählen

for question, answer in zip(questions, answers):
    print(question)
    while True:
        answer = input("Your Answer (A, B, or C):")
        if answer in ("A", "B", "C"):
            break
    points, rights, wrongs = answer_check(answer, points, rights, wrongs)
    print("Points: {}\nCorrect answers: {}\nWrong answers: {}".format(points, rights, wrongs)
Benutzeravatar
MrBrightside
User
Beiträge: 10
Registriert: Dienstag 14. November 2017, 16:01

@ sirius3

Danke für die schnelle Antwort. Ich war mir nicht bewusst, das ich im "Hauptcode" die Ergebnisse der Funktion wieder in die Variablen einlesen muss.
Das solution nicht definiert war, ist lediglich ein Flüchtigkeitsfehler beim Abtippen gewesen.

Herzlichen Dank für die Hilfe
Benutzeravatar
/me
User
Beiträge: 3554
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

MrBrightside hat geschrieben:Ich war mir nicht bewusst, das ich im "Hauptcode" die Ergebnisse der Funktion wieder in die Variablen einlesen muss.
Es ist unter anderem Sinn und Zweck einer Funktion, unabhängig vom Aufrufer arbeiten zu können. Auch die Namen der Bezeichner müssen nicht gleich sein.

Code: Alles auswählen

def calculate(a, b):
    a += 1
    b -= 1
    return a / b

x = 7
y = 3
x, y, z = calculate(x, y)
Werte betreten eine Funktion über Parameter und verlassen sie durch Rückgabe mit return.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@/me: Dein Beispiel funktioniert nicht, weil Du nur einen Rückgabewert hast.

Ganz einfach läßt sich die Unklarheit beantworten, wenn man sich fragt, was hier passieren soll:

Code: Alles auswählen

z = calculate(4, 7)
Benutzeravatar
/me
User
Beiträge: 3554
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Sirius3 hat geschrieben:@/me: Dein Beispiel funktioniert nicht, weil Du nur einen Rückgabewert hast.
Na toll. Ich bin ein Schnarchsack. Es hätte so aussehen sollen:

Code: Alles auswählen

def calculate(a, b):
    a += 1
    b -= 1
    return a, b, a / b
     
x = 7
y = 3
x, y, z = calculate(x, y)
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

So ganz knusper ist das Verwenden von __iadd__ und __isub__ auf a und b nicht. Irgendwann fliegt einem die Übergabe per Referenz hier um die Ohren.
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@bwbg: Das kommt darauf an, ob die übergebenen Parameter mutable oder immutable Objekte sind. Bei immutablen Objekten werden die inplace-Operatoren zu zweistufigen Anweisungen. Zunächst die Operation selbst, anschließend Zuordnung des neuen Objektes an ein bestehendes Label im aktiven Namensraum. Bei mutablen Datentypen sieht es anders aus, da entfällt der zweite Schritt. Wer das nicht beachtet, für den mag das Ergebnis überraschend sein.
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

Eben. Es kommt auf einen Umstand an, welcher sich einem nur sehr beschwerlich erschließt.

Meines Erachtens sollte davon ausgegangen werden, dass __iadd__ und Konsorten das Objekt verändern können, die korrespondierenden Methoden (__add__, etc.) ein neues Objekt zurückgeben.
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@bwbg: genau, bei »a + b« ist sichergestellt, dass sich weder a noch b ändern, alles andere wäre sehr verwirrend. Bei »a += b« dagegen kann man sich weder darauf verlassen, dass a danach noch das selbe Objekt enthält, noch, dass sich das ursrprüngliche a nicht verändert hat. Man muß eben lernen, wie sie welches Objekt verhält; das ist wie mit den unregelmäßigen Verben.
Antworten