Funktionen und Rückgabewerte

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
Patsche
User
Beiträge: 43
Registriert: Samstag 23. Oktober 2021, 00:17

Hi!

Ich habe bisher immer mit globalen Variablen gearbeiten, was ja aber nicht gut ist. Das möchte ich jetzt ändern.
Jetzt habe ich aber ein Problem, wie ich Rückgabewerte von Funktionen.
Mir fällt es auch immer schwer beispiele aus dem Internet zu verstehen, weil ich nie so recht weiß, welches Wort nun eine Variable ist, die selbst ausgedacht ist, oder ob das Wort schon belegt ist, wie beispielsweise "print". Erschwerend kommt hinzu, dass vieles auf englisch geschrieben wird. Wäre es auf deutsch, dann könnte ich das ja rausfiltern, weil belegte "Wörter" halt auf englisch wären und der Rest auf deutsch.
Aber egal.
Hier habe ich mal ein kleines Beispiel geschrieben:

Code: Alles auswählen

def addieren(a,b):
    c=a+b
    return c
    
def subtrahieren(a,b):
    c=a-b
    return c

def multiplizieren(a,b):
    c=a*b
    return c

def dividieren(a,b):
    c=a/b
    return c

a=int(input("Bitte Zahl 1 eingeben: "))
b=int(input("Bitte Zahl 2 eingeben: "))
print("Was möchten Sie mit den Zahlen tun?")
print("    1.addieren")
print("    2.subtrahieren")
print("    3.multiplizieren")
print("    4.dividieren")

auswahl=int(input("Ihre Antwort:  "))

if auswahl==1:
    addieren(a,b)
    print("Ergebnis: ",c)

elif auswahl==2:
    subtrahieren(a,b)
    print("Ergebnis: ",c)

elif auswahl==3:
    multiplizieren(a,b)
    print("Ergebnis: ",c)

elif auswahl==4:
    dividieren(a,b)
    print("Ergebnis: ",c)
Das Programm möchte vom Benutzer 2 Zahlen haben und fragt dann, was mit diesen gemacht werden soll. Klar bräuchte man jetzt keine Funktionen, aber ich möchte ja genau das gerade lernen.
Ok also weiter:
Der Funktion werden die Zahlen in a und b übergeben und in der Definition der Funktion habe ich auch definiert, dass ihr a und b übergeben werden muss.
Das verstehe ich auch.
In der Funktionen werden a und b verarbeitet und in c gespeichert.
Die Funktion gibt das Ergebnis in c wieder durch das "return" zurück.
Jetzt soll c ausgegeben werden, aber ich bekomme halt den Fehler, dass c nicht definiert wurde.
Hier ist eben mein Problem.
Die Funktion soll c zurückgeben, aber das passiert ja nicht.
Kann mir da jemand helfen und den Code entsprechen hier posten?

Vielen Dank für eure Hilfe!
Zuletzt geändert von Patsche am Sonntag 24. Oktober 2021, 13:15, insgesamt 1-mal geändert.
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Patsche,

"c" ist nur innerhalb der Funktionen definiert. Um den Wert von "c" ausserhalb der Funktion verwenden zu können, must du den Funktionsaufruf einer oder mehrerer Variablen zuweisen:

Code: Alles auswählen

if auswahl==1:
    ergebnis = addieren(a,b)
    print("Ergebnis: ", ergebnis)
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Funktion gibt einen Wert zurück, aber mit dem Wert machst Du nichts. Es ist das selbe, wie bei den Funktionen `input` und `int`, die Du ja korrekt benutzt:

Code: Alles auswählen

def subtrahieren(a, b):
    c = a - b
    return c

ergebnis = subtrahieren(17, 6)
print(ergebnis)
Prinzipiell kannst Du jeden Namen, der kein Schlüsselwort ist, benutzen, also auch `print = 17`. Probleme bekommst Du, wenn Du `print` zum Ausgeben benutzen willst.
Benutzeravatar
Patsche
User
Beiträge: 43
Registriert: Samstag 23. Oktober 2021, 00:17

rogerb hat geschrieben: Sonntag 24. Oktober 2021, 13:07 @Patsche,

"c" ist nur innerhalb der Funktionen definiert. Um den Wert von "c" ausserhalb der Funktion verwenden zu können, must du den Funktionsaufruf einer oder mehrerer Variablen zuweisen:

Code: Alles auswählen

if auswahl==1:
    ergebnis = addieren(a,b)
    print("Ergebnis: ", ergebnis)
Ja so klappt es, wenn ich a und b nehme.
Ich möchte ja aber nicht mit a und b weitermachen, sondern mit der Variable c.


So klappt es leider auch nicht:

Code: Alles auswählen

if auswahl==1:
    addieren(a,b)
    c=addieren(c)
    print(c)
So erstelle ich doch eine neue Variable c und weise ihr den Wert der Variable c aus der Funktion zu. Aber das klappt auch nicht.
Das muss doch irgendwie möglich sein. Oder macht man das eben auch nicht?
Sirius3 hat geschrieben: Sonntag 24. Oktober 2021, 13:08 Prinzipiell kannst Du jeden Namen, der kein Schlüsselwort ist, benutzen, also auch `print = 17`. Probleme bekommst Du, wenn Du `print` zum Ausgeben benutzen willst.
Ja eben. Wenn man aber nicht alle Schlüsselwörter kennt und dann Beispiele anguckt, wo die Wörter auf englisch und nicht farblich hervorgehoben werden, dann weißß ich nie, ob das jetzt ein Schlüsselwort ist oder eben nciht.......
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Code: Alles auswählen

if auswahl==1:
    addieren(a,b)
    
    # Das "c" in der Klammer wird zuerst ausgewertet, ist zu dem Zeitpunkt aber noch unbekannt. Daher gibt es einen Fehler
    c=addieren(c)
    print(c)
Daher:

Code: Alles auswählen

if auswahl==1:
    c = addieren(a,b)
    print(c)
Benutzeravatar
Patsche
User
Beiträge: 43
Registriert: Samstag 23. Oktober 2021, 00:17

Und genau da liegt mein Denkproblem. Warum ist das (c) noch nicht verfügbar?
Ich ruf ja die Funktion auf und errechnen den Wert aus a und b und rechne das Funktions c aus gebe ihn als c zurück.
Also muss doch das "Funktions c" schon abgearbeitet worden sein.
Wieso ist es denn nicht verfügbar, wenn ich es in das "Haupt-C" schieben will?
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Dann kommen wir der Sache schon näher. Du hast anscheinen angenommen, dass die Namen, die in der Funktion definiert werden auch außerhalb definiert sind. Das ist nicht der Fall.

Code: Alles auswählen

def function():
    a = 10

# Ergibt einen NameError
print(a)
Das ist auch gut so sonst, gäbe es ein riesiges Durcheinander. Über den Rückgabewert hat man die Kontrolle, was aus der Funktion wieder nach außen gelangt.
So funktioniert es. Auch wenn ich hier außerhalb und innerhalb der Funktion "a" verwende, gelangt der Wert von a innerhalb der Funktion nur über die Rückgabe an das "a" außerhalb der Funktion.

Code: Alles auswählen

def function():
    a = 10
    return a

a = function()
print(a)
Zuletzt geändert von rogerb am Sonntag 24. Oktober 2021, 14:16, insgesamt 1-mal geändert.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Du bist immer noch in diesen "globalen" Denkstrukturen gefangen und musst dich davon lösen.
Die Variable c ist jeweils nur innerhalb der Funktion definiert und nicht außerhalb.
Um den errechneten Wert außerhalb der Funktion weiterverwenden zu können gibt man ihn per return an den Aufruf zurück.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
Patsche
User
Beiträge: 43
Registriert: Samstag 23. Oktober 2021, 00:17

ThomasL hat geschrieben: Sonntag 24. Oktober 2021, 14:15 Die Variable c ist jeweils nur innerhalb der Funktion definiert und nicht außerhalb.
Und warum ist es das?
Wir bleiben jetzt beispielhaft hier:

Code: Alles auswählen

def addieren(a,b):
    c=a+b
    return c
Hier habe ich c innerhalb der Funktion definiert. Soweit richtig. Das vetsehe ich. Und auch das c nicht außerhalb verfügbar ist.
Und hier der Teil im Hauptprogramm:

Code: Alles auswählen

if auswahl==1:
    addieren(a,b)    <-----------------
    c=addieren(c)
    print(c)
Ich rufe die Funktion auf und erhalte das c zurück.

Code: Alles auswählen

if auswahl==1:
    addieren(a,b)   
    c=addieren(c) < -----------------
    print(c)
Nun möchte ich das "Funktions c" ind das "Haupt c" schreiben. Das geht scheinbar aber nicht, weil das Funktions c halt nicht verfügbar ist.


Deshlab muss ich mir behelfen, dass ich es so aufrufe:

Code: Alles auswählen

if auswahl==1:
    c=addieren(a,b) 
    print(c)
Ich muss also das Haupt c so deklarieren, dass ich der Funktion a und b übergebe und den Rückgabewert direkt dort hineinschreibe.
Ich muss also beides gleichzeitg machen.
Statt erst die Funktion aufzurufen und dann den Rückgabewert in eine Variable zuschreiben

Code: Alles auswählen

if auswahl==1:
    addieren(a,b) 
    c=addieren(c)
    print(c)
muss ich das in einem Rutsch machen.

Code: Alles auswählen

if auswahl==1:
    c=addieren(a,b) 
    print(c)
So langsam wird es mir beim Ausformulieren gerade klar.
Vielen Dank an euch!!!!!!!!!
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Wie gesagt:

Wenn hier

Code: Alles auswählen

if auswahl==1:
    addieren(a,b) 
    c=addieren(c)
    print(c)
die Zeile

Code: Alles auswählen

c = addieren(c)
abgearbeitet wird, schaut Python zuerst auf den rechten Teil des Gleichheitszeichens:

Code: Alles auswählen

... = addieren(c)
Da "c" bis dahin noch nicht im Haupt definiert wurde, kann Python nichts damit anfangen.

Das ist kein Behelf, sondern die richtige und einzige Vorgehensweise:

Code: Alles auswählen

if auswahl==1:
    c=addieren(a,b) 
    print(c)
Benutzeravatar
Patsche
User
Beiträge: 43
Registriert: Samstag 23. Oktober 2021, 00:17

rogerb hat geschrieben: Sonntag 24. Oktober 2021, 14:47 Da "c" bis dahin noch nicht im Haupt definiert wurde, kann Python nichts damit anfangen.

Code: Alles auswählen

if auswahl==1:
    addieren(a,b) 
    c=addieren(c) <-------------
    print(c)
Ich bin davon ausgegangen, dass das c, wenn es innerhalb des Funktionsausdrucks geschrieben wird, das Funktions c gemeint ist.
Ist aber eben nicht so.
Das Problem ist eben, dass die Funktion nicht wirklcih das Funktions c zurückgibt, sondern "nur" den Wert, der in diesem Funktions c steht.
Sehe ich es denn richtig, dass man niemals direkt auf Variablen einer Funktion zurückgreifen kann, sondern nur auf deren Inhalt?
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Sehe ich es denn richtig, dass man niemals direkt auf Variablen einer Funktion zurückgreifen kann, sondern nur auf deren Inhalt?
Das ist richtig, der Wert ist innerhalb der Funktion an einen Namen gebunden. Bei der Rückgabe an einen Namen außerhalb der Funktion wird nur der Wert an den neuen Namen außerhalb der Funktion gebunden. Namen wie du es zunächst dachtest, werden nicht übergeben.

Genauso ist es auch beim Aufruf der Funktion.

Code: Alles auswählen

addieren(c)
Hier wird nicht die Variable "c" irgendwie in die Funktion verschoben, sondern der Wert, von "c" wird an den Funktionsparameter welcher in der Funktionsdeklaration an der entsprechenden Stelle steht übergeben.

Code: Alles auswählen

def function(a, b):
    print(a)
    print(b)

c = 1
d = 2

function(c, d)

"""
Ausagbe:
1
2
"""
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Patsche hat geschrieben: Sonntag 24. Oktober 2021, 14:59 Sehe ich es denn richtig, dass man niemals direkt auf Variablen einer Funktion zurückgreifen kann, sondern nur auf deren Inhalt?
Nein, immer noch falsch. Du kannst von außen auf gar nichts innerhalb einer Funktion zugreigen, aber die Funktion kann Werte entgegennehmen - die Argumente - und einen Wert zurückgeben - den sog. return value. Schau mal:

Code: Alles auswählen

def add(a, b):
    return a + b

c = add(a, b)
Hier gibt es überhaupt kein c innerhalb der Funktion, sondern nur a und b und trotzdem bekommst du einen return value.

Tatsächlich macht add(a, b) genau dasselbe wie a + b. Letzteres ist auch nur ein Funktions-Aufruf, allerdings syntaktisch mittels eines sog. Infix-Operators dargestellt. Infix, weil der Operator "in" der Mitte des Ausdrucks steht, nicht davor, wie bei add(a, b). Du fragst dich ja auch nicht, wie du auf das c - oder welchen Buchstaben auch immer - innerhalb der +-Funktion zugreifen kannst. Und außerdem wäre es ziemlich schlecht, wenn man auf die Interna einer Funktion zugreifen könnte, denn dann müsste man überall den aufrufenden Code anpassen, wenn man an diesen Interna etwas ändert. Stell dir vor, irgendeine Bibliothek würde das machen, die von Millionen Programmierern verwendet wird - dann müssten alle diese Programmierer jedesmal ihren Code anpassen, wenn sich an der Bibliothek etwas ändert. Und das ist eben genau der Witz von Funktionen: dass die Interna dem Aufrufer egal sein können, denn der ist letztlich nur an dem Ergebnis interessiert, nicht daran, wie das Ergebnis zustande kommt. Du willst ja auch nicht den Führerschein jedes mal neu machen, wenn an deinem Auto eine Schraube ausgetauscht wird.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
__blackjack__
User
Beiträge: 13073
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Patsche: Nur so allgemein als Ergänzung: Solche trivialen Funktionen die den Effekt von Operatoren nachbauen brauchst Du nicht selbst schreiben. Die gibt es in der Standardbibliothek im `operator`-Modul schon fertig.

Die ``if``/``elif``-Zweige sehen auch alle irgendwie gleich aus. Die unterscheiden sich ja nur durch die Funktion die verwendet wird um aus `a` und `b` den Wert `c` auszurechnen. Und die Funktion wird anhand von einer Zahl ausgewählt. Wenn man also die Funktionen in einer Liste hätte, könnte man die passende einfach über den Index auswählen.

Code: Alles auswählen

#!/usr/bin/env python3
from operator import (
    add as addieren,
    mul as multiplizieren,
    sub as subtrahieren,
    truediv as dividieren,
)


def main():
    a = int(input("Bitte Zahl 1 eingeben: "))
    b = int(input("Bitte Zahl 2 eingeben: "))

    functions = [addieren, subtrahieren, multiplizieren, dividieren]
    print("Was möchten Sie mit den Zahlen tun?")
    print("    1. addieren")
    print("    2. subtrahieren")
    print("    3. multiplizieren")
    print("    4. dividieren")

    index = int(input("Ihre Antwort: ")) - 1
    print("Ergebnis:", functions[index](a, b))


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten