Multiparameter an Funktion über Input() ü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.
thomas07
User
Beiträge: 10
Registriert: Dienstag 5. November 2013, 19:49

Hallo zusammen,

bin neu in diesem schönen Forum und möchte erstmal alle begrüßen.

Meine Frage:
Wie kann ich Multiparameter über Input an eine Funktion übegerben?

Beispielsweise folgender Code funktioniert nicht:

Code: Alles auswählen

def mittelwert(*arg):
    return sum(arg) / len(arg)

zahlen = input("Werte eingeben! ")
print("Der Mittelwert beträgt: " + mittelwert(zahl))

# Wenn die Werte direkt im Code eingegeben werden, dann geht's!
#print("Der Mittelwert beträgt: " + mittelwert(1, 2, 3))
Ich weiß, dass das Format von Input() str ist und *arg Tupel braucht.

Wie kann ich denn die Konvertierung am einfachsten durchführen?

Danke vorab

Viele Grüße
Thomas
BlackJack

@thomas07: Als erstes solltest Du den ``*`` aus der Funktionssignatur von `mittelwert()` nehmen und das Argument vielleicht besser benennen. Dann stellst sich beim Aufruf das Problem erst gar nicht.

Und die Eingabe musst Du halt entsprechend umwandeln. Zum Beispiel an einem bestimmten Zeichen aufteilen und dann die Einzelteile, die ja immer noch Zeichenketten sind, in Zahlen umwandeln. Das sind Grundlagen die man eigentlich in jedem Grundlagentutorial lernt. In der Python-Dokumentation ist eines und für absolute Anfänger wird oft Learn Python The Hard Way empfohlen. (Nicht vom Titel irritieren lassen.)
thomas07
User
Beiträge: 10
Registriert: Dienstag 5. November 2013, 19:49

Hallo,

danke erstmal für die prompte Antwort.
BlackJack hat geschrieben:@thomas07: Als erstes solltest Du den ``*`` aus der Funktionssignatur von `mittelwert()` nehmen und das Argument vielleicht besser benennen. Dann stellst sich beim Aufruf das Problem erst gar nicht.
Wenn ich den Stern wegnehme, dann kann ich ja nicht unbestimmte Anzahl an Argumenten an die Funktion übergeben, aber ich will ja gerade * verwenden.
Der Code sollte NUR ein Beispiel sein - also Benennung sollte kein Problem darstellen....
BlackJack hat geschrieben:Und die Eingabe musst Du halt entsprechend umwandeln. Zum Beispiel an einem bestimmten Zeichen aufteilen und dann die Einzelteile, die ja immer noch Zeichenketten sind, in Zahlen umwandeln. Das sind Grundlagen die man eigentlich in jedem Grundlagentutorial lernt.
Ja, daran hatte ich auch gedacht, aber auch das hat nicht funktioniert:

Code: Alles auswählen

zahlen = input("Werte eingeben! ")
liste1 = zahlen.split(sep=",")
liste2 = []
for i in liste1:
    liste2.append(int(i))
zahlen=tuple(liste2)
print("Der Mittelwert beträgt: " + mittelwert(zahl))
BlackJack hat geschrieben:In der Python-Dokumentation ist eines und für absolute Anfänger wird oft Learn Python The Hard Way empfohlen. (Nicht vom Titel irritieren lassen.)
Danke für die Empfehlungen - ich werde sie mir anschauen.

Gruß
Thomas
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

thomas07 hat geschrieben:Ja, daran hatte ich auch gedacht, aber auch das hat nicht funktioniert: ...
Nun, wenn du `*` weglaesst schon.

Daneben ist Zeile 6 ueberfluessig und du willst dir List Comprehensions anschauen, dann werden auch Zeilen 2-5 zu einer.
thomas07
User
Beiträge: 10
Registriert: Dienstag 5. November 2013, 19:49

Hallo,
cofi hat geschrieben:Nun, wenn du `*` weglaesst schon.
Genau, das will ich ja nicht.

Also, mir geht's bei meiner Frage um die Verwendung von * als beliebige Anzahl von Parameteren. Ich hätte gerne gewusst, ob es eine Möglichkeit besteht, Input-Werte (Zahlen) als Tupel an *arg zu übergeben.

Gruß
Thomas
BlackJack

@thomas07: Warum bestehst Du so störrisch auf das ``*`` was die Sache nur unnötig kompliziert macht. Dann übergibst Du genau *ein* Argument, das kann aber eine Sequenz, zum Beispiel eine Liste mit beliebig vielen Werten sein. Und Du brauchst beim Aufruf keine ”Magie”.
thomas07
User
Beiträge: 10
Registriert: Dienstag 5. November 2013, 19:49

BlackJack hat geschrieben:@thomas07: Warum bestehst Du so störrisch auf das ``*`` was die Sache nur unnötig kompliziert macht. Dann übergibst Du genau *ein* Argument, das kann aber eine Sequenz, zum Beispiel eine Liste mit beliebig vielen Werten sein. Und Du brauchst beim Aufruf keine ”Magie”.
Wie geschrieben, es geht mir nur um die Verwendung von * - ich will nichts konkretes implementieren.
Ich bin in der Lernphase und möchte die Dinge verstehen und nicht umgehen.
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

thomas07 hat geschrieben:Wie geschrieben, es geht mir nur um die Verwendung von * - ich will nichts konkretes implementieren.
Ich bin in der Lernphase und möchte die Dinge verstehen und nicht umgehen.
Das Problem ist, dass hier das Unpacking völlig sinnlos ist.
zikzak
User
Beiträge: 21
Registriert: Sonntag 22. September 2013, 07:28
Wohnort: Sipbachzell, Österreich

Vielleicht trifft es das:

Code: Alles auswählen

# -*- coding: utf-8 -*-

mittelwert = lambda *z: sum(*z) / len(*z)

zahlen = input("Zahlen eingeben! (durch , getrennt) ")
print (mittelwert ([float(x) for x in zahlen.split(sep=",")]))
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

@zikzak: Um ... das macht es um einiges schlimmer.

Statt 1-dimensionalen Argumenten, beliebig viele Zahlen ~ Liste von Zahlen, erwartest du jetzt 2-dimensionale, beliebig viele Listen von Zahlen ~ Liste von Liste von Zahlen.

Ueber die unsinnige Verwendung von lambda seh ich mal hinweg ...
thomas07
User
Beiträge: 10
Registriert: Dienstag 5. November 2013, 19:49

Hallo zikzak,

danke für die Unterstützung und den Code.
zikzak hat geschrieben:Vielleicht trifft es das:

Code: Alles auswählen

# -*- coding: utf-8 -*-

mittelwert = lambda *z: sum(*z) / len(*z)

zahlen = input("Zahlen eingeben! (durch , getrennt) ")
print (mittelwert ([float(x) for x in zahlen.split(sep=",")]))
Ja, das hat mich in der Tat weitergebracht :idea:

Du übergibst eine Liste als *Arg und ich habe die ganze Zeit gedacht, dass *Arg Tupel braucht :cry:

Nun klappt es auch in meinem Beispiel mit List.

Ich habe allerdings immer noch etwas Verständnisproblem und zwar:
Ich habe festgestellt, wenn die Werte "direkt" als *Arg übergeben werden, dann muss man die Sterne in sum() und len() weglassen.
Wie in folgendem Beispiel mittelwert1:

Code: Alles auswählen

def mittelwert1(*arg):
    print(type(arg))
    return sum(arg) / len(arg)
 
print("Der Mittelwert betraegt: %f" %mittelwert1(1,2,3))
Als welcher Datentyp wird hier 1,2,3 übergeben - doch nicht als List, oder??

Wenn aber das Argument als Liste übergeben wird, dann braucht man die Sterne überall, wie in diesem Beispiel mittelwert2:

Code: Alles auswählen

def mittelwert2(*arg):
    print(type(arg))
    return sum(*arg) / len(*arg)
   
zahlen = input("Werte eingeben! ")
 
liste = zahlen.split(sep=",")
for i in liste:
    liste[liste.index(i)] = float(i)
 
print("Der Mittelwert betraegt: %f" %mittelwert2(liste))
Wenn ich aber in mittelwert1 und mittelwert2 den Datentyp von arg ausgeben lasse, dann wird in beiden Fällen Tupel ausgegeben:

Code: Alles auswählen

<class 'tuple'>
Viele Grüße
Thomas
Zuletzt geändert von thomas07 am Mittwoch 6. November 2013, 00:16, insgesamt 1-mal geändert.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ja, *args werden zu Tupeln, wobei es aber komplett egal ist ob es Tupel, Listen oder sonstige indizierbare Datenstrukturen sind.

Deine Erkenntnis zu "mittelwert2" ist genau das, was wir die ganze Zeit schon darstellen wollen: Wie du die Funktion benutzt und wie du sie definierst passt nicht zusammen.
zikzak
User
Beiträge: 21
Registriert: Sonntag 22. September 2013, 07:28
Wohnort: Sipbachzell, Österreich

Auf der Seite von "BlackJack" - http://blog.marc.rintsch.de/2012/11/18/ ... nbook.html habe ich folgenden Code gefunden:

Code: Alles auswählen

def average(iterable, start_value=0):
    total = start_value
    i = None
    for i, value in enumerate(iterable):
        total += value
    if i is None:
        raise ValueError('iterable must contain at least one argument.')
    return total / (i + 1)
thomas07
User
Beiträge: 10
Registriert: Dienstag 5. November 2013, 19:49

Hallo,

statt

Code: Alles auswählen

for i in liste:
    liste[liste.index(i)] = float(i)
könnte ich auch folgendes schreiben:

Code: Alles auswählen

liste = list(map(float, liste))
Gruß
Thomas
BlackJack

Oder man zieht gleich ein bisschem mehr in einen Ausruck zusammen und gibt der Liste mit den Zahlen den Namen `zahlen` statt den für eine Zeichenkette zu verwenden und die Zahlen an den sehr allgemeinen Namen `liste` zu binden:

Code: Alles auswählen

    zahlen = list(map(float, input('Werte eingeben! ').split(',')))
thomas07
User
Beiträge: 10
Registriert: Dienstag 5. November 2013, 19:49

Guten Morgen BlackJack,

ja, das ist auch eine gute Idee und die Benennung ist auch mit Zahl sinnvoller.

Viele Grüße
Thomas
Benutzeravatar
snafu
User
Beiträge: 6847
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

BlackJack hat geschrieben:Oder man zieht gleich ein bisschem mehr in einen Ausruck zusammen und gibt der Liste mit den Zahlen den Namen `zahlen` statt den für eine Zeichenkette zu verwenden und die Zahlen an den sehr allgemeinen Namen `liste` zu binden:

Code: Alles auswählen

    zahlen = list(map(float, input('Werte eingeben! ').split(',')))
Oder man nutzt gleich eine List Comprehension:

Code: Alles auswählen

zahlen = [float(zahl) for zahl in input('Werte eingeben: ').split(',')]
BlackJack

@snafu: Aber das verbraucht doch so viel mehr Zeichen im Quelltext. :-)
Benutzeravatar
snafu
User
Beiträge: 6847
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

BlackJack hat geschrieben:@snafu: Aber das verbraucht doch so viel mehr Zeichen im Quelltext. :-)
:(
thomas07
User
Beiträge: 10
Registriert: Dienstag 5. November 2013, 19:49

Hallo zusammen,

wenn ich so genau hinschaue, stellt sich mir die Frage: Warum hatt map() keinen direkt verwendbaren Rückgabewert und muss erst mit list, tuple usw. konvertiert werden, zumal man ja ihr eine Sequenz übergibt.

Ich würde von map() einen Rückgabetyp wie der Typ der übergebenen Sequenz.

Was meint Ihr dazu?

Viele Grüße
Thomas
Antworten