Seite 1 von 2
list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 08:10
von Judge
Guten morgen zusammen,
ich möchte gerne Werte in einer Liste für einen mehrteiligen Format String nutzen (Python 2).
Folgenden Anfang habe ich:
Aus dem String mache ich eine Liste, indem ich "string.rsplit('-', 1)" mache; da fällt ja die Liste "['This-is', 'SPARTAAA!']" heraus.
Wie kann ich das jetzt ohne Zwischenvariablen und ohne das ich da mit zwei Aufrufen und slices arbeite dem Format String übergeben?
Folgendes klappt natürlich:
Code: Alles auswählen
string = "This-is-SPARTAAA!"
print '%s %s' % (string.rsplit('-', 1)[0], string.rsplit('-', 1)[1])
und
Code: Alles auswählen
string = "This-is-SPARTAAA!"
a, b = string.rsplit('-', 1)
print '%s %s' % (a, b)
Aber da muss es doch noch elegantere Wege geben, oder?
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 08:49
von Alfons Mittelmeyer
Judge hat geschrieben:
Code: Alles auswählen
string = "This-is-SPARTAAA!"
a, b = string.rsplit('-', 1)
print '%s %s' % (a, b)
Aber da muss es doch noch elegantere Wege geben, oder?
Was findest Du da nicht elegant?
a) Du hast einen String: das läßt sich nicht vermeiden
b) Du splittest den String: das läßt sich auch nicht vermeiden
c) Du gibst den String formatiert aus: wenn Du das vermeidest, kannst Du auch a und b vermeiden. Wäre das eleganter?
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 09:06
von Judge
Hi Alfons,
zum Beispiel würde ich gerne zusätzliche Variablen vermeiden.
Es wäre total cool, wenn es dafür einen Kniff gäbe.
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 09:16
von Alfons Mittelmeyer
Judge hat geschrieben:Hi Alfons,zum Beispiel würde ich gerne zusätzliche Variablen vermeiden.
Es wäre total cool, wenn es dafür einen Kniff gäbe.
Code: Alles auswählen
print '%s %s %s' % tuple("This-is-SPARTAAA!".split('-'))
War das der Kniff?
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 09:18
von noisefloor
Hallo,
ja gibt es. Wobei ich nicht "kniff" nennen würde, weil es in der offiziellen Doku der .format() Methode von String erklärt ist.
Außerdem möchtest du nicht `rsplit()` verwenden (macht keinen Sinn hier), sondern `split()`, weil damit direkt alles gesplittet wird.
So geht's mit Python 2.7:
[codebox=pycon file=Unbenannt.txt]>>> my_string = 'foo-bar-spamegg'
>>> print '{} {} {}'.format(*my_string.split('-'))
foo bar spamegg
>>>
[/code]
Gruß, noisefloor
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 09:21
von bwbg
Das Verwenden der %-Formatierung für Strings sollte durch die format-Methode ersetzt werden. Weiter Informationen findest Du unter
https://docs.python.org/2/library/strin ... matstrings der offiziellen Python-Dokumentation.
Für deinen konkreten Fall ließe sich das so herleiten:
[codebox=pycon file=Unbenannt.txt]>>> text = 'This-is-SPARTAAA!'
>>> text.split('-', 1)
['This', 'is-SPARTAAA!']
>>> '{} {}'.format('This', 'is-SPARTAAA!')
'This is-SPARTAAA!'
>>> '{} {}'.format(*text.split('-', 1))
'This is-SPARTAAA!'[/code]
Was es mit dem magischen Sternchen (*text ...) auf sich hat, erfährst Du unter
https://docs.python.org/2.7/glossary.ht ... -parameter
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 09:26
von Alfons Mittelmeyer
noisefloor hat geschrieben:
So geht's mit Python 2.7:
[codebox=pycon file=Unbenannt.txt]>>> my_string = 'foo-bar-spamegg'
print '{} {} {}'.format(*my_string.split('-'))
[/code]
Nein bereits ab python 2.6
Aber genannt war nur python 2 und version ???
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 09:31
von noisefloor
Hallo,
Nein bereits ab python 2.6
Habe auch nie was anderes behauptet.
Aber genannt war nur python 2 und version ???
Und genau darum habe ich geschrieben, mit welcher Python-Version ist das gemacht habe. Könnte ja sein, dass jemand unter einer dicken Staubschicht noch ein Python 2.5 oder 2.4 gefunden hat.
Gruß, noisefloor
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 10:11
von kbr
bwbg hat geschrieben:Das Verwenden der %-Formatierung für Strings sollte durch die format-Methode ersetzt werden.
Das halte ich für eine Konvention, die projektbezogen festgelegt werden kann, denn die %-Formatierung ist m.W. nicht deprecated.
Die schnellste Möglichkeit einen String zusammenzusetzen ist der + Operator, gefolgt von der %-Formatierung mit der .format-Methode als langsamste Implementierung. Mit der Abnahme der Geschwindigkeit nimmt jedoch die Zahl und Flexibilität der Formatierungsmöglichkeiten sowie der Parameterübergabe zu.
Üblicherweise geht in Python Lesbarkeit vor Geschwindigkeit, bis sich letzteres negativ bemerkbar macht — was bei String-Formatierungen sicher nur selten der Fall ist, da denen oft irgendeine I/O-Routine folgt, die noch langsamer ist. Es ist aber dennoch gut, die Unterschiede zu kennen; es kann immer Situationen geben, in denen dies nützlich ist.
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 10:12
von Alfons Mittelmeyer
noisefloor hat geschrieben:
So geht's mit Python 2.7:
[codebox=pycon file=Unbenannt.txt]>>> my_string = 'foo-bar-spamegg'
>>> print '{} {} {}'.format(*my_string.split('-'))
foo bar spamegg
>>>
[/code]
Nö noisefloor, das geht nicht in python 2.7.
format geht, aber
* geht nicht.
Probiere doch mal:
Das geht erst in python 3.
Also die richtige Lösung für python 2:
Code: Alles auswählen
print '%s %s %s' % tuple("This-is-SPARTAAA!".split('-'))
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 10:52
von BlackJack
@Alfons Mittelmeyer: Das was noisefloor geschrieben hat geht mit Python 2.7 (und auch 2.6). ``*`` bei Funktionsaufrufen geht sogar in noch früheren Python-Versionen. Das ``print`` in Python 2 ein Schlüsselwort und keine Funktion ist, hat damit nichts zu tun, denn das hat noisefloor weder behauptet noch benutzt, wie man dem Code ja deutlich sehen kann.
Zudem geht auch ``print(*(1, 2, 3))`` ab Python 2.6 wenn man aus dem `__future__`-Modul `print_function` importiert:
Code: Alles auswählen
from __future__ import print_function
print(*(1, 2, 3))
Gibt unter Python 2.7 ``1 2 3`` auf der Konsole aus.
Wenn man keine Ahnung hat…
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 16:49
von Alfons Mittelmeyer
Du magst es ja als magisch bezeichnen, und es ist auch sehr nützlich, aber es zeigt auch ganz deutlich die unsaubere und inkonsistente Semantik von python:
Code: Alles auswählen
# statt:
print(1,2,3)
# geht auch
print (*(1,2,3))
# aber statt
print(5 + 1,2,3)
# geht nicht
print(5 + *(1,2,3))
# auch geht solches nicht
print(*(1,2,3) + 5)
# es geht aber noch
print(5, *(1,2,3))
# aber das schon nicht mehr
print(*(1,2,3),5)
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 17:07
von BlackJack
@Alfons Mittelmeyer: Das einzige davon das nicht geht und vielleicht auf den ersten Blick überraschend ist, ist das letzte Beispiel. Alles andere sollte man erwarten wenn man Python's Semantik verstanden hat.
Zum Beispiel ist das Äquivalent zu ``print(5 + 1, 2, 3)`` als ``*``-Form ``print(*(5 + 1, 2, 3))``. Wie man auf die abwegige Idee kommen kann die ``5 +`` vor dieses Konstrukt zu schreiben, in der irrigen Hoffnung das würde sich dann auf das erste Element in dem Tupel beziehen ist mir ein Rätsel. Ohne die ”Magie” des ``*`` beim Funktionsaufruf ginge das mit einem Tupel ja auch nicht ``5 + (1, 2, 3)`` ist ja auch nicht möglich um das gleiche Ergebnis wie ``(5 + 1, 2, 3)`` zu erhalten. Und genau so wenig wie man eine Zahl und ein Tupel addieren kann, kann man halt auch ein Tupel und eine Zahl nicht addieren.
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 17:31
von Alfons Mittelmeyer
BlackJack hat geschrieben:@Alfons Mittelmeyer: Das einzige davon das nicht geht und vielleicht auf den ersten Blick überraschend ist, ist das letzte Beispiel. Alles andere sollte man erwarten wenn man Python's Semantik verstanden hat.
Zum Beispiel ist das Äquivalent zu ``print(5 + 1, 2, 3)`` als ``*``-Form ``print(*(5 + 1, 2, 3))``. Wie man auf die abwegige Idee kommen kann die ``5 +`` vor dieses Konstrukt zu schreiben, in der irrigen Hoffnung das würde sich dann auf das erste Element in dem Tupel beziehen ist mir ein Rätsel.
Das sind doch keine abwegige Gedanken, betrachten wir uns:
Der Operator "
+" ist ein binärer Operator. Und das '
*' ist in diesem Fall ein unärer Operator. Unäre Operatoren haben allgemein Vorrang vor binären Operatoren. Daher sollte von der Semantik her zuerst das Tuple expandiert werden, wonach dann die 5 zum ersten Element addiert werden kann. Aber hier gibt es einen Syntax Error. Der Parser parst auf einen mathematischen Ausdruck und erwartet einen Rechtswert. Dabei sieht er wohl fälschlicherweise das '*' als den binären Multiplikationsoperator an und wirft einen SyntaxError.
Es ist derselbe Fehler, wie bei:
Dieses und das übrige Verhalten erklärt sich natürlich daraus, daß hier das '*' gar kein normaler unärer Operator ist, sondern hier '*' den letzten Teil einer positionellen Argumentliste expandiert und danach müssen keyword Argumente folgen, welche zudem die Funktion 'print' auch gar niicht kennt.
'*' ist also nicht einfach die Expandierung eines Tuples sondern die Expandierung eines Tuples als letzer Teil der positionellen Funktionsargumente.
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 18:45
von BlackJack
@Alfons Mittelmeyer: Doch das sind abwegige Gedanken. Das ``*`` ist in diesem Fall *gar kein* Operator sondern das ”magische” Zeichen das man *vor* ein Argument beim Aufruf schreibt. Und dieses Argument muss ein Ausdruck sein, der zu einem iterierbaren Objekt ausgewertet wird.
Und selbst wenn man solche abwegigen Gedanken hat, kann man ja auch einfach mal die Dokumentation lesen statt sich Verhalten erraten oder wünschen zu wollen. Dann ist man weniger überrascht wenn man mal wieder falsch geraten hat.
Die `print()`-Funktion kennt Schlüsselwortargumente. Wie gut das Du Dich so gut mit den Grundlagen von Python auskennst.

Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 19:12
von Alfons Mittelmeyer
BlackJack hat geschrieben:Die `print()`-Funktion kennt Schlüsselwortargumente. Wie gut das Du Dich so gut mit den Grundlagen von Python auskennst.

Und was ist das?
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 19:16
von BlackJack
@Alfons Mittelmeyer: Das ist wieder typischer Unsinn von Dir. `print()` kennt Schlüsselwortargumente. Und wenn der Programmierer die kennt, kann er sie auch verwenden und Werte dafür übergeben. Du kennst sie halt nicht, wie so vieles was mit Python zu tun hat. Kann man aber in der Dokumentation nachlesen.
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 19:21
von Alfons Mittelmeyer
BlackJack hat geschrieben:@Alfons Mittelmeyer: Das ist wieder typischer Unsinn von Dir. `print()` kennt Schlüsselwortargumente. Und wenn der Programmierer die kennt, kann er sie auch verwenden und Werte dafür übergeben. Du kennst sie halt nicht, wie so vieles was mit Python zu tun hat. Kann man aber in der Dokumentation nachlesen.
Da bist Du im Irrtum, ich kenn das sehr wohl. Aber möchte nur darauf hinweisen, dass die Python Semantik verwirrend sein kann, für jemand der einsteigt und mit anderen Sprachen vertraut ist
.
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 20:31
von BlackJack
@Alfons Mittelmeyer: Ach, dafür kann man einfach auf Deine gesammelten Beiträge verweisen.

Andererseits ist das aber auch eine ziemlich banale Erkenntniss. Die Semantik von jeder Programmiersprache kann verwirrend sein für jemanden der mit anderen Sprachen vertraut ist.
Re: list für mehrteiligen format string verwenden?
Verfasst: Dienstag 16. Mai 2017, 22:49
von Sirius3
Nachdem Alfons Mittelmeyer wieder einen Thread kaputt geschrieben hat, zurück zum Thema. rsplit liefert eine Liste und format kann auch die Elemente einer Liste ausgeben, ganz ohne Magie:
Code: Alles auswählen
string = "This-is-SPARTAAA!"
print '{0[0]} {0[1]}'.format(string.rsplit('-', 1))