Eingaben einer Funktion übergeben?

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
Intregral
User
Beiträge: 20
Registriert: Montag 15. März 2021, 13:35

Hallo liebe ExpertInnen,
ich rätsele grade über folgendem Code ( das ist die Aufgabe 13 aus Weitz, Konkrete Mathematik. 2. Auflage. 2021:11)

Code: Alles auswählen

#  Schreiben Sie eine Python-Funktion, die zwei Argumente akzeptiert und von den beiden das zurückgibt, das weiter von null entfernt ist. Wenn die Argumente 3 und −7 sind, soll also z.B. −7 zurückgegeben werden.

a = int(input("Bitte Zahl eingeben "))
b = int(input("Bitte Zahl eingeben "))

def weit(a, b): #Funktion mit zwei Paramtern
    if a < 0: #Betrag von a bestimmen
        betrag_a = 0-a
    if a > 0:
        betrag_a = a
   
    if b < 0: #Betrag von a bestimmen
        betrag_b = 0-b
    if b > 0:
        betrag_b = b
            
    if betrag_a == betrag_b: #Zwei gleiche Zahlen
        print("Beide Werte sind gleich weit von 0 entfernt")
        return #Ende :)

    if betrag_a > betrag_b: #größeren Betrag ausgeben
      
        return a
    else:
        return b
Wenn ich die Funktion ganz normal aufrufe (ohne die beiden Inputs am Anfang), dann macht das Skript was es soll.
Mit den Inputs fragt das Programm die beiden Zahlen ab und stoppt dann...warum werden hier "a" und "b" nicht an die Funktion übergeben?

(Bitte nicht über meine Lösung der Aufgabe lachen, ich bin mir sicher dass das sehr umständlich ist mit den beiden Beträgen...) ;)
einfachTobi
User
Beiträge: 512
Registriert: Mittwoch 13. November 2019, 08:38

Du rufst die Funktion nicht auf.
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Die Lösung für das Problem wurde ja bereits gegeben. Hier ist jetzt eine alternative Implementierung.

Wir stecken a und b in eine Liste und sortieren diese. Das Sortierkriterium (key) ist dabei der absolute Wert der Zahl. Jetzt braucht man nur noch das letzte Element (also das an Index 1) der sortierten Folge nehmen und schon ist man fertig.

Code: Alles auswählen

def weiter_von_null_entfernt(a, b):
    return sorted([a, b], key=abs)[1]
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Intregral: Eine Funktion sollte in jedem Fall etwas zurück geben und nicht entweder eine Zahl oder implizit `None`. Und ein `print()` gehört da auch nicht hinein.

Die Aufgabenstellung spezifiziert den Fall nicht, das beide Eingaben gleich weit von 0 entfernt sind. Da könntest Du Dir dann ein sinnvolles Verhalten überlegen. Beispielsweise das dann `a` *oder* `b` zurückgegeben wird, oder das eine Ausnahme ausgelöst wird.

Für den Betrag hat Python übrigens eine Funktion. Betrag heisst auf eglisch „absolute value“, falls das beim suchen dieser Funktion helfen könnte. Selbst wenn Du diese Funktion nicht verwenden darfst, würde man sich so eine Funktion dann selbst schreiben, denn Du brauchst das ja offensichtlich *zweimal* in Deiner Funktion.

Deren Name `weit()` etwas komisch ist. Die würde man eher `maximaler_betrag()` nennen.

@/me: Zu umständlich; `max()` hat auch ein `key`-Argument:

Code: Alles auswählen

from functools import partial

weit = partial(max, key=abs)

print(weit(3, -7))
Ausgabe:
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Intregral
User
Beiträge: 20
Registriert: Montag 15. März 2021, 13:35

__blackjack__ hat geschrieben: Dienstag 30. März 2021, 16:16 @Intregral: Eine Funktion sollte in jedem Fall etwas zurück geben und nicht entweder eine Zahl oder implizit `None`. Und ein `print()` gehört da auch nicht hinein.

Die Aufgabenstellung spezifiziert den Fall nicht, das beide Eingaben gleich weit von 0 entfernt sind. Da könntest Du Dir dann ein sinnvolles Verhalten überlegen. Beispielsweise das dann `a` *oder* `b` zurückgegeben wird, oder das eine Ausnahme ausgelöst wird.

Für den Betrag hat Python übrigens eine Funktion. Betrag heisst auf eglisch „absolute value“, falls das beim suchen dieser Funktion helfen könnte. Selbst wenn Du diese Funktion nicht verwenden darfst, würde man sich so eine Funktion dann selbst schreiben, denn Du brauchst das ja offensichtlich *zweimal* in Deiner Funktion.

Deren Name `weit()` etwas komisch ist. Die würde man eher `maximaler_betrag()` nennen.

@/me: Zu umständlich; `max()` hat auch ein `key`-Argument:

Code: Alles auswählen

from functools import partial

weit = partial(max, key=abs)

print(weit(3, -7))
Ausgabe:
Ok, dass es eine Betragsfunktion gibt wird im genannten Buch sogar gesagt: "Python hat schon so eine Funktion, aber wir wollen ja was lernen. . ."

Das die Aufgabe subotimal ist wird auch direkt gesagt:
"Aufgabe 14: Begründen Sie, warum die letzte Aufgabe nicht ausreichend präzise
beschrieben hat, was die Funktion machen soll. Wie kann man die Aufgabe besser
formulieren?"

Das habe ich ja eigentlich gemacht indem ich bei Zahlengleichheit diese ausgebe.

Es geht halt im Buch darum mit den aktuell bekannten und eingeführten Elementen die Aufgabe zu lösen. Das sind auf Seite 11 halt nur Variablen, Fuktionen, if..else und while...Ich will das ja Schritt für Schritt lernen. (Das mit dem Input ist schon von mir vorweggegriffen...) :D

Ich hab es mal so versucht:

Code: Alles auswählen

def weit(a, b):
    
    a = input("Bitte Zahl eingeben ")
    b = input("Bitte Zahl eingeben ")
    
    if a < 0: #Betrag von a bestimmen
        betrag_a = 0-a
    if a > 0:
        betrag_a = a
   
    if b < 0: #Betrag von a bestimmen
        betrag_b = 0-b
    if b > 0:
        betrag_b = b
            
    if betrag_a == betrag_b: #Zwei gleiche Zahlen
        print("Beide Werte sind gleich wert von 0 entfernt")
        return #Ende :)

    if betrag_a > betrag_b: #größeren Betrag ausgeben
      
        return a
    else:
        return b
Python schweigt aber...
Intregral
User
Beiträge: 20
Registriert: Montag 15. März 2021, 13:35

__blackjack__ hat geschrieben: Dienstag 30. März 2021, 16:16 @Intregral: Eine Funktion sollte in jedem Fall etwas zurück geben und nicht entweder eine Zahl oder implizit `None`. Und ein `print()` gehört da auch nicht hinein.

Die Aufgabenstellung spezifiziert den Fall nicht, das beide Eingaben gleich weit von 0 entfernt sind. Da könntest Du Dir dann ein sinnvolles Verhalten überlegen. Beispielsweise das dann `a` *oder* `b` zurückgegeben wird, oder das eine Ausnahme ausgelöst wird.

Für den Betrag hat Python übrigens eine Funktion. Betrag heisst auf eglisch „absolute value“, falls das beim suchen dieser Funktion helfen könnte. Selbst wenn Du diese Funktion nicht verwenden darfst, würde man sich so eine Funktion dann selbst schreiben, denn Du brauchst das ja offensichtlich *zweimal* in Deiner Funktion.

Deren Name `weit()` etwas komisch ist. Die würde man eher `maximaler_betrag()` nennen.

@/me: Zu umständlich; `max()` hat auch ein `key`-Argument:

Code: Alles auswählen

from functools import partial

weit = partial(max, key=abs)

print(weit(3, -7))
Ausgabe:
Das mit der Funktion zweimal stimmt natürlich wie ich jetzt auch sehe...aber ich habe für den Code schon eine gute Stunde gebraucht..also Nachsicht... :oops:

Zu der Absolutfunktion hab ich oben schon was geschrieben.

Jedenfalls erstmal vielen Dank an euch, ich muss mir das jetzt in Ruhe anschauen. Oder ich guck einfach in den Lösungsteil vom Buch wenn ich gar nicht weiterkomme... :D
Intregral
User
Beiträge: 20
Registriert: Montag 15. März 2021, 13:35

P.S. Ich hab die Funktion so dämlich genannt weil die eigentlich in der Konsole aufgerufen werden sollte, und da wollte ich zum testen nicht immer ein ellenlanges Wort schreiben.... :wink:
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Intregral: Python ”schweigt” weil Du die Funktion auch aufrufen musst. Machst Du in der Konsole ja auch, und auch dort wird die erst *dann* ausgeführt. Im Gegensatz zur Konsole fehlt dann noch ein `print()` um etwas auszugeben.

Die `input()`-Aufrufe gehören nicht in die Funktion. Und in der Funktion etwas mit `print()` ausgeben ist auch nicht der richtige Weg mit der ”Unterspezifikation” in der Aufgabe umzugehen, denn davon bekommt der Aufrufer der Funktion nichts mit. Der will in dem Fall vielleicht auch etwas ganz anderes machen als eine Ausgabe, oder eine andere Ausgabe die spezifischer für das Problem ist weshalb die Funktion aufgerufen wurde.

Du musst die Beiträge übrigens nicht komplett zitieren. Die stehen doch direkt darüber; man braucht nur ein bisschen hoch scrollen. 🙂

Edit: Machst Du nicht alle Aufgaben? Zumindest in der ersten Auflage des Buches ist die Aufgabe vor dieser Aufgabe sich eine Funktion zu schreiben die den Absolutbetrag einer gegebenen Zahl zurück gibt. *Da* ist dann auch als Fussnote die Bemerkung, dass es eine solche Funktion auch schon fertig gibt.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
ThomasL
User
Beiträge: 1379
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Mal als Beispiel wie eine Lösung aussehen könnte:

Code: Alles auswählen

"""
Schreiben Sie eine Python-Funktion, die zwei Argumente akzeptiert und von den beiden das zurückgibt,
das weiter von null entfernt ist. Wenn die Argumente 3 und −7 sind, soll also z.B. −7 zurückgegeben werden.
"""

def absolute(number):
    if number < 0:
        number *= -1
    return number

def weiter(a, b):
    if absolute(a) > absolute(b):
        return a
    else:
        return b

def main():
    x = int(input("Bitte 1. Zahl eingeben: "))
    y = int(input("Bitte 2. Zahl eingeben: "))
    print(weiter(x, y))
    
if __name__ == '__main__':
    main()
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
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Intregral: Was die Namenslänge angeht: Verwendest Du nicht wie im Anhang von dem Buch beschrieben ein Jupyter Notebook um Code interaktiv auszuführen? Das hat Tab-Vervollständigung für Namen, also Namensanfang schreiben, Tab-Taste drücken und den Namen aus dem Dropdown auswählen, schon muss man nicht so viel tippen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Intregral
User
Beiträge: 20
Registriert: Montag 15. März 2021, 13:35

__blackjack__ hat geschrieben: Dienstag 30. März 2021, 19:22 @Intregral: Python ”schweigt” weil Du die Funktion auch aufrufen musst. Machst Du in der Konsole ja auch, und auch dort wird die erst *dann* ausgeführt. Im Gegensatz zur Konsole fehlt dann noch ein `print()` um etwas auszugeben.

Die `input()`-Aufrufe gehören nicht in die Funktion. Und in der Funktion etwas mit `print()` ausgeben ist auch nicht der richtige Weg mit der ”Unterspezifikation” in der Aufgabe umzugehen, denn davon bekommt der Aufrufer der Funktion nichts mit. Der will in dem Fall vielleicht auch etwas ganz anderes machen als eine Ausgabe, oder eine andere Ausgabe die spezifischer für das Problem ist weshalb die Funktion aufgerufen wurde.

Du musst die Beiträge übrigens nicht komplett zitieren. Die stehen doch direkt darüber; man braucht nur ein bisschen hoch scrollen. 🙂

Edit: Machst Du nicht alle Aufgaben? Zumindest in der ersten Auflage des Buches ist die Aufgabe vor dieser Aufgabe sich eine Funktion zu schreiben die den Absolutbetrag einer gegebenen Zahl zurück gibt. *Da* ist dann auch als Fussnote die Bemerkung, dass es eine solche Funktion auch schon fertig gibt.
Eigentlich mache ich alle Aufgaben. Die Aufgabe für die Betragsfunktion hab ich zuvor gelöst.

Ich denke man braucht einfach Erfahrung um parat zu haben dass man ja eine schon geschriebene Funktion einfach recyclen kann, mal als Beispiel.

Dass man keinen Input-/Print-Befehl in eine Funktion schreibt leuchtet mir jetzt auch völlig ein, weil das dem Konzept der Funktion ja zuwider läuft. Nur ging es mir jetzt hauptsächlich darum, die Aufgabe zu lösen, nicht darum Funktionen zu schreiben die andere nutzen können. Das Programm macht ja, was verlangt ist (und sogar noch mehr), und das freut mich erst mal. Dass es immer auch andere und oft auch bessere Wege gibt ist mir klar.

Nochmal, ich bin komplett am Anfang und lerne gern dazu. :wink:
Intregral
User
Beiträge: 20
Registriert: Montag 15. März 2021, 13:35

__blackjack__ hat geschrieben: Dienstag 30. März 2021, 20:00 @Intregral: Was die Namenslänge angeht: Verwendest Du nicht wie im Anhang von dem Buch beschrieben ein Jupyter Notebook um Code interaktiv auszuführen? Das hat Tab-Vervollständigung für Namen, also Namensanfang schreiben, Tab-Taste drücken und den Namen aus dem Dropdown auswählen, schon muss man nicht so viel tippen.
Für kurze Experimente Tests etc. nehm ich fast immer erst ein Notebook, für komplette Sachen dann lieber Spyder, da mir das sonst bei den ganzen kurzen Schnipseln pro Notebook zu unübersichtlich wird. Sammle immer einfach zu viel an in den Notebooks, dann finde ich nix wieder... :lol:

Das mit der Tab-Taste wusste ich gar nicht, danke für den Tipp...
Intregral
User
Beiträge: 20
Registriert: Montag 15. März 2021, 13:35

ThomasL hat geschrieben: Dienstag 30. März 2021, 19:46 Mal als Beispiel wie eine Lösung aussehen könnte:

Code: Alles auswählen

"""
Schreiben Sie eine Python-Funktion, die zwei Argumente akzeptiert und von den beiden das zurückgibt,
das weiter von null entfernt ist. Wenn die Argumente 3 und −7 sind, soll also z.B. −7 zurückgegeben werden.
"""

def absolute(number):
    if number < 0:
        number *= -1
    return number

...
[/quote]

Vielen Dank für den Vorschlag.

Da hätte ich natürlich drauf kommen müssen, einfach die Zahl positiv machen per Multiplikation mit -1.  :roll:
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei ich das unnötig umständlich finde. Du warst da ein einer einfacheren Lösung schon deutlich näher, denn statt ``number = 0 - number`` könnte man auch einfach ``number = -number`` schreiben.

In der Lösung zum Buch wird der bedingte Ausdruck eingeführt:

Code: Alles auswählen

def absolute(number):
    return -number if number < 0 else number
Mit dem Hinweis kann dann die Lösung zu Aufgabe 13 auch zu einem Einzeiler werden:

Code: Alles auswählen

def get_maximum_distance(a, b):
    return a if absolute(a) > absolute(b) else b
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Intregral
User
Beiträge: 20
Registriert: Montag 15. März 2021, 13:35

Dass man einfach ein Minus vor eine Variable setzen kann hätte ich jetzt nicht vermutet. Da ist Python wohl doch einfacher als ich erst dachte. Ich hätte vermutet dass man dafür eine spezielle Funktion braucht.

Die Multiplikation mit -1 ist ja ein korrekter mathematischer Weg, um immer den Betrag zu erzeugen (wenn es nicht gerade um eine kompexe Zahl geht), deshalb ärgert mich das dass ich das nicht bedacht habe. :wink:
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Intregral: Als Funktion gibt's das unäre Minus auch, wie alle Operatoren als Funktion im `operator`-Modul verfügbar sind:

Code: Alles auswählen

In [235]: operator.neg(-42)                                                     
Out[235]: 42

In [236]: operator.neg(23)                                                      
Out[236]: -23
Manchmal ist es ganz nützlich Operatoren als Funktionen irgendwo übergeben zu können.

Code: Alles auswählen

In [237]: list(map(operator.neg, [-23, 42, -4711, 0, math.inf]))                
Out[237]: [23, -42, 4711, 0, -inf]
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten