list für mehrteiligen format string verwenden?

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.
Benutzeravatar
Judge
User
Beiträge: 129
Registriert: Mittwoch 13. Juni 2012, 22:27
Wohnort: Ratingen
Kontaktdaten:

Guten morgen zusammen,

ich möchte gerne Werte in einer Liste für einen mehrteiligen Format String nutzen (Python 2).
Folgenden Anfang habe ich:

Code: Alles auswählen

string = "This-is-SPARTAAA!"
print '%s %s' % ????????
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?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

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?
Benutzeravatar
Judge
User
Beiträge: 129
Registriert: Mittwoch 13. Juni 2012, 22:27
Wohnort: Ratingen
Kontaktdaten:

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.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

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?
Zuletzt geändert von Alfons Mittelmeyer am Dienstag 16. Mai 2017, 09:22, insgesamt 1-mal geändert.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

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
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

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
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

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 ???
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

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
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

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.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

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:

Code: Alles auswählen

print( *(1,2,3))
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('-'))
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…
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

bwbg hat geschrieben:Was es mit dem magischen Sternchen (*text ...) auf sich hat, erfährst Du unter https://docs.python.org/2.7/glossary.ht ... -parameter
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)
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.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

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:

Code: Alles auswählen

print(5 + *(1, 2, 3))
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:

Code: Alles auswählen

print(1 + *5)
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.
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. ;-)
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

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?

Code: Alles auswählen

name = 3
print(1,2,3,name=4)
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.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

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
.
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.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

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))
Antworten