Seite 1 von 2
Aus Summen kürzen nur die Dummen
Verfasst: Freitag 8. Mai 2009, 10:16
von 4bit
Hallo,
sum([1,2,3]) funktioniert wunderbar, aber sum(["hallo", " du", " da!"]) nicht.
Gibt es keinen Python Standard, um strings aus Listen zu addieren?
Immerhin "funktioniert "+"das hier" ohne Probleme.
Grüße,
4bit-
Verfasst: Freitag 8. Mai 2009, 10:19
von numerix
Verfasst: Freitag 8. Mai 2009, 10:26
von 4bit
ah, super, Danke.
Verfasst: Freitag 8. Mai 2009, 12:40
von Leonidas
Genauer: sum nimmt zwei Argumente, einmal das Iterable das aufsummiert werden soll und einen Startwert. Dieser Startwert ist standardmäßig 0 und daher kommt "TypeError: unsupported operand type(s) for +: 'int' and 'str'" (``0 + "Hallo"`` funktioniert eben nicht). Wenn man nun aber als zweiten Parameter den leeren String angibt, "", dann kommt "TypeError: sum() can't sum strings [use ''.join(seq) instead]", wo einem explizit gesagt wird was zu tun ist. Lustige Fehlermeldung

Verfasst: Freitag 8. Mai 2009, 14:11
von derdon
Es geht auch anders
Code: Alles auswählen
In [676]: from operator import add
In [677]: reduce(add, ['Hallo ', 'du ', 'da'])
Out[677]: 'Hallo du da'
Re: Aus Summen kürzen nur die Dummen
Verfasst: Freitag 8. Mai 2009, 15:42
von birkenfeld
@derdon: Argh!
Verfasst: Samstag 9. Mai 2009, 12:15
von derdon
Und hier nochmal in schön
Code: Alles auswählen
In [739]: join_string = lambda strings, sep='': reduce(lambda a, b: (lambda a, b, sep: a + sep + b)(a, b, sep), strings)
In [740]: join_string(['Hallo', 'du', 'da'])
Out[740]: 'Halloduda'
In [741]: join_string(['Hallo', 'du', 'da'], ' ')
Out[741]: 'Hallo du da'
Edit: Und hier in einem Rutsch:
Code: Alles auswählen
In [745]: (lambda strings, sep='': reduce(lambda a, b: (lambda a, b, sep: a + sep + b)(a, b, sep), strings))(('Hallo', 'du', 'da'), ' ')
Out[745]: 'Hallo du da'
Verfasst: Samstag 9. Mai 2009, 13:04
von Nocta
Könnte man die sum Funktion nicht so schreiben, dass sie als Startwert einen Typ nimmt, der sowohl Strings als auch Integer (und sonstige numerische Datentypen) addieren kann bzw jeweils den Datentyp annimmt, der benötigt wird?
Strings in Listen zu addieren zu können, wäre ja eigentlich logisch, weil man sie ja auch mittels + addieren kann.
Wenn Strings und Zahlen gemixt sind, müssten die Zahlen halt als String angesehn werden, anders macht das dann wieder keinen Sinn.
Verfasst: Samstag 9. Mai 2009, 13:16
von Leonidas
Also soll quasi die Funktion erraten was du vor hast? Das klingt nach einer sehr schlechten Idee. Explicit is better than implicit.
Und Strings in Listen sollte man eben nicht addieren, genau dafür gibt es ja auch ``join``, was das bevorzugte Werkzeug ist (und die Fehlermeldung sagt das auch so).
Verfasst: Samstag 9. Mai 2009, 13:20
von snafu
Das ist doch wohl schnell selbst gemacht:
Code: Alles auswählen
In [6]: def new_sum(sequence, start=0):
...: try:
...: return sum(sequence, start=start)
...: except TypeError:
...: return ''.join(sequence)
...:
...:
In [7]: new_sum(["hallo", " du", " da!"])
Out[7]: 'hallo du da!'
@Leonidas:
Lustig ist IMHO nicht nur die Fehlermeldung, sondern auch die Doku:
Docstring:
sum(sequence, start=0) -> value
Returns the sum of a sequence of numbers (NOT strings) plus the value
of parameter 'start'. When the sequence is empty, returns start.
Vielleicht tobt da ja intern irgendein Kampf, ob man Strings nun annehmen sollte oder nicht.

Verfasst: Samstag 9. Mai 2009, 13:40
von Nocta
Leonidas hat geschrieben:Also soll quasi die Funktion erraten was du vor hast? Das klingt nach einer sehr schlechten Idee. Explicit is better than implicit.
Wieso erraten?
Eindeutig definiert:
Sind Strings vorhanden, werden Strings addiert.
Sind (nur) Zahlen vorhanden, werden die Zahlen summiert.
Ist beides vorhanden, wird alles als String angesehen und addiert.
Das einzige wirkliche Problem würde ich darin sehen, dass das die sum-Methode wahrscheinlich deutlich verlangsamen würde, wenn man große Listen erstmal nach Strings überprüfen muss, damit die Funktion entscheiden kann, was zu tun ist.
Also Beispielsweise bei Listen, die so aussehen:
Hier weiß das Programm ja erstmal nicht (bevor es nicht erst 999999999 Elemente überprüft hat), ob Strings enthalten sind, und man folglich die Zahlen als Strings addieren soll.
Aber man könnte den 3. Punkt auch einfach weglassen und spart sich diese Probleme. Es ist eh nicht so "schön" einfach Strings und Zahlen als Strings zu addieren und wahrscheinlich auch unnötig. Dann nimmt man sich einfach das erste Element und addiert den rest drauf. Wenn Strings und Zahlen vermischt sind kann man dann ja immer noch einen Error ausgeben

Verfasst: Samstag 9. Mai 2009, 13:47
von snafu
@Nocta:
Ich kenne die genaue Implementierung von `sum()` nicht, aber höchstwahrscheinlich wird der `TypeError` da auch erst geworfen, wenn die 1 Million Elemente durchlaufen wurden und er auf einen String stößt.
Verfasst: Samstag 9. Mai 2009, 14:02
von veers
Code: Alles auswählen
TypeError: sum() can't sum strings [use ''.join(seq) instead]
Wie kann man diese Exception eigentlich nicht verstehen?
Jonas
Verfasst: Samstag 9. Mai 2009, 14:18
von Nocta
snafu hat geschrieben:@Nocta:
Ich kenne die genaue Implementierung von `sum()` nicht, aber höchstwahrscheinlich wird der `TypeError` da auch erst geworfen, wenn die 1 Million Elemente durchlaufen wurden und er auf einen String stößt.
Das denke ich mir auch.
Aber wenn man zulassen will, dass Strings und Zahlen gemixt addiert werden können, muss man im vorhinein wissen, ob dies passieren soll, weil die Zahlen ja sonst alle summiert würden, anstatt als String addiert zu werden. Deshalb wäre sum() für Strings
und Zahlen gleichzeitig wohl zu unperformant (je nachdem, was für eine Liste es ist), um es zuzulassen.
Aber was spricht denn eigentlich dagegen, sum für Strings zuzulassen?
Also so in etwa wie du (snafu) es als Codebeispiel gepostet hast.
@veers: Verstehn tut die glaube ich jeder. Und es versteht auch jeder, dass es join() gibt. Aber ich sehe keine Notwendigkeit, das in 2 Funktionen (sum für Zahlen und join für Strings) aufzuteilen. Aber wenn jemand ein (gerne auch mehrere) Argument dafür hat, ändere ich meine Meinung gerne.
Verfasst: Samstag 9. Mai 2009, 14:32
von lunar
Nocta hat geschrieben:Aber was spricht denn eigentlich dagegen, sum für Strings zuzulassen?
Man kann Zeichenketten nicht
addieren, die Summe ist eine arithmetische Funktion. Zeichenkette kann man allenfalls zusammenfügen. sum() für Zeichenketten ist einfach unlogisch. Zudem wäre das fehleranfällig, da eine vergessene Typkonvertierung anstatt einer geordneten Ausnahme eine unerwartete Konkatenation zur Folge hätte. Unpraktisch wäre es auch, da man Zeichenketten oft auch mit bestimmten Trennzeichen zusammenfügen möchte (z.B.
'\n'.join(sequence)). Die Implementierungen wären auch komplett unterschiedlich, zumindest, wenn man sie effizient gestalten möchte.
Schlussendlich aber ist diese Diskussion eh müßig. Das Verhalten ist durch die Dokumentation nun mal so festgelegt, also wirst du damit leben müssen. Für Diskussionen um Veränderungen der Bibliothek bzw. der Sprache ist die python-dev-Liste da.
Verfasst: Samstag 9. Mai 2009, 14:42
von snafu
Erstmal würde man bei meiner Version wie gesagt alles durchlaufen bis zu einem Fehler/Exception sobald ein String erkannt wird und dann nochmal neu anfangen und außerdem machen `join()` und `sum()` 2 grundsätzlich unterschiedliche Sachen. Lunar hat das ja schon im Detail erläutert.
Ich find's eigentlich ganz gut, so wie es jetzt ist. Etwas ungewöhnlich finde ich nur, dass der Trenner nicht als Argument innerhalb der Klammer übergeben wird, sondern eben am Anfang stehen muss. Der Hintergrund ist klar: `join()` ist eine Methode der `str`-Klasse. Die Frage ist aber, ob das wirklich so sinnvoll gewählt ist...
Verfasst: Samstag 9. Mai 2009, 14:51
von veers
lunar hat geschrieben:Nocta hat geschrieben:Aber was spricht denn eigentlich dagegen, sum für Strings zuzulassen?
Man kann Zeichenketten nicht
addieren
Jonas
Verfasst: Samstag 9. Mai 2009, 15:25
von lunar
Danke, dass du meine Argumentation kaputt gemacht hast.

Verfasst: Samstag 9. Mai 2009, 18:15
von birkenfeld
snafu hat geschrieben:
Ich kenne die genaue Implementierung von `sum()` nicht, aber höchstwahrscheinlich wird der `TypeError` da auch erst geworfen, wenn die 1 Million Elemente durchlaufen wurden und er auf einen String stößt.
Und das ist nicht nur höchstwahrscheinlich, sondern sicher flasch. Viel einfacher: die Exception muss man nur auslösen, wenn das zweite Argument ein String ist.
Vielleicht tobt da ja intern irgendein Kampf, ob man Strings nun annehmen sollte oder nicht.
Glaub mir, da haben wir ganz andere Sachen zu tun...

Verfasst: Samstag 9. Mai 2009, 19:47
von Leonidas
Nocta hat geschrieben:Leonidas hat geschrieben:Also soll quasi die Funktion erraten was du vor hast? Das klingt nach einer sehr schlechten Idee. Explicit is better than implicit.
Wieso erraten?
Eindeutig definiert:
Sind Strings vorhanden, werden Strings addiert.
Sind (nur) Zahlen vorhanden, werden die Zahlen summiert.
Ist beides vorhanden, wird alles als String angesehen und addiert.
Und was wenn Tupel, Dicts, Listen, eigene Datentypen drin sind, die ``__add__`` definieren, aber eine Addition mit Strings unsinnig ist?