Wie kann ich str- und int-Objekte verketten?

73

Wenn ich Folgendes versuche:

things = 5
print("You have " + things + " things.")

In Python 3.x wird der folgende Fehler angezeigt:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be str, not int

... und ein ähnlicher Fehler in Python 2.x:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

Wie kann ich dieses Problem umgehen?

Null Piräus
quelle

Antworten:

111

Das Problem hierbei ist, dass der +Operator in Python (mindestens) zwei verschiedene Bedeutungen hat: Für numerische Typen bedeutet dies "Addiere die Zahlen zusammen":

>>> 1 + 2
3
>>> 3.4 + 5.6
9.0

... und für Sequenztypen bedeutet es "die Sequenzen verketten":

>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
>>> 'abc' + 'def'
'abcdef'

In der Regel konvertiert Python Objekte nicht implizit von einem Typ in einen anderen 1 , um Operationen "sinnvoll" zu machen, da dies verwirrend wäre: Sie könnten beispielsweise denken, dass dies '3' + 5bedeuten sollte '35', aber jemand anderes könnte dies für sinnvoll halten gemein 8oder sogar '8'.

In ähnlicher Weise können Sie mit Python keine zwei verschiedenen Sequenztypen verketten:

>>> [7, 8, 9] + 'ghi'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list

Aus diesem Grund müssen Sie die Konvertierung explizit durchführen, unabhängig davon, ob Sie Verkettung oder Addition wünschen:

>>> 'Total: ' + str(123)
'Total: 123'
>>> int('456') + 789
1245

Es gibt jedoch einen besseren Weg . Abhängig von der verwendeten Python-Version stehen drei verschiedene Arten der Zeichenfolgenformatierung zur Verfügung 2 , mit denen Sie nicht nur mehrere +Vorgänge vermeiden können :

>>> things = 5

>>> 'You have %d things.' % things  # % interpolation
'You have 5 things.'

>>> 'You have {} things.'.format(things)  # str.format()
'You have 5 things.'

>>> f'You have {things} things.'  # f-string (since Python 3.6)
'You have 5 things.'

... aber Sie können auch steuern, wie Werte angezeigt werden:

>>> value = 5
>>> sq_root = value ** 0.5
>>> sq_root
2.23606797749979

>>> 'The square root of %d is %.2f (roughly).' % (value, sq_root)
'The square root of 5 is 2.24 (roughly).'

>>> 'The square root of {v} is {sr:.2f} (roughly).'.format(v=value, sr=sq_root)
'The square root of 5 is 2.24 (roughly).'

>>> f'The square root of {value} is {sq_root:.2f} (roughly).'
'The square root of 5 is 2.24 (roughly).'

Ob Sie % Interpolation , str.format()oder f-Strings sind bis zu Ihnen:% Interpolation um die längste war (und ist bekannt für Menschen mit einem Hintergrund in C), str.format()ist oft stärker, und f-Strings sind mächtiger noch ( aber nur in Python 3.6 und höher verfügbar).

Eine andere Alternative besteht darin, die Tatsache zu verwenden, dass bei Angabe printmehrerer Positionsargumente deren Zeichenfolgendarstellungen mithilfe des sepSchlüsselwortarguments (standardmäßig ' ') zusammengefügt werden:

>>> things = 5
>>> print('you have', things, 'things.')
you have 5 things.
>>> print('you have', things, 'things.', sep=' ... ')
you have ... 5 ... things.

... aber das ist normalerweise nicht so flexibel wie die Verwendung der in Python integrierten Funktionen zur Formatierung von Zeichenfolgen.


1 Obwohl dies eine Ausnahme für numerische Typen darstellt, bei denen sich die meisten Menschen auf das „Richtige“ einigen würden:

>>> 1 + 2.3
3.3
>>> 4.5 + (5.6+7j)
(10.1+7j)

2 Eigentlich vier ... aber Vorlagenzeichenfolgen werden selten verwendet und sind etwas umständlich.

Null Piräus
quelle
3
Diese Antwort ist insofern großartig, als sie sowohl Hintergrundinformationen als auch mehrere Lösungen bietet, die tatsächlichen Lösungen jedoch in der Mitte einer Textwand vergraben sind. Es würde zu Beginn von einem TLDR profitieren (als eine Form der progressiven Offenlegung ).
Helen
13
@Helen diese kanonische Frage / Antwort ist bewusst als Köder & Schalter geschrieben - die Frage hat einen "Gimme the Codez" -Stil, während die Antwort darauf abzielt, nicht sofort eine "Gimme the Codez" -Lösung bereitzustellen. Ich bin nicht der Meinung, dass der Ansatz der umgekehrten Pyramide / progressiven Offenlegung gut für den Unterricht auf Anfängerebene geeignet ist. Es verbessert die offensichtliche Produktivität von schlechten Programmierern (die tatsächlich den "tl" -Rest "dr" machen) auf Kosten derer, die später ihren Code pflegen. Ich möchte potenziell großartigen Programmierern lieber helfen als definitiv schrecklichen, und versuche, einen entsprechenden Beitrag zu SO zu leisten.
Zero Piraeus
9

TL; DR

  1. print("You have " + str(things) + " things.") (der "alte Schule" Weg)

  2. print("You have {} things.".format(things)) (der neue pythonische und empfohlene Weg)

  3. print(f"You have {things} things.") (wie die coolen Kids das machen: P)

  4. print("You have", things, "things.") (wie @wjandrea in den Kommentaren hervorhob)


Eine etwas verbalere Erklärung:
Obwohl die oben genannte ausgezeichnete Antwort von @Zero Piraeus nichts enthält, werde ich versuchen, sie ein wenig zu "minimieren" :
Sie können eine Zeichenfolge und eine Zahl (jeglicher Art) in Python wegen dieser Objekte nicht verketten unterschiedliche Definitionen des Plus (+) - Operators haben, die nicht miteinander kompatibel sind (Im str-Fall wird + für die Verkettung verwendet, im Zahlenfall werden zwei Zahlen addiert). Um dieses "Missverständnis" zwischen Objekten zu lösen:

  1. Die alte Methode besteht darin, die Zahl mit der str(anything)Methode in eine Zeichenfolge umzuwandeln und das Ergebnis dann mit einer anderen Zeichenfolge zu verketten.
  2. Die pythonischere und empfohlene Methode ist die Verwendung der Formatierungsmethode , die sehr vielseitig ist (Sie müssen nicht mein Wort darauf nehmen, die Dokumentation und diesen Artikel lesen ).

Viel Spaß und Sie lesen die @Zero Piraeus beantworten es sicherlich wert Ihre Zeit!

John Moutafis
quelle
3
Diese Antwort fügt nichts Neues hinzu.
Ethan Furman
Wenn Sie Ihre Antwort jetzt löschen, erhalten Sie ein Abzeichen dafür (erinnern Sie sich nicht an den Namen, aber Sie löschen eine Antwort mit mindestens 3 positiven Stimmen).
Ethan Furman
3
@ EthanFurman Ich denke, Sie suchen dies :) stackoverflow.com/help/badges/37/disciplined
Adam
1
@Ethan Furman Es gibt nichts, was wirklich zu dieser Antwort hinzugefügt werden kann. Ich habe nur versucht, sie ein wenig zu minimieren und die Nachfrage nach einem TL; DR von Helen zu befriedigen! Das Kanonische ist bei weitem die Antwort von Zero Piraeus!
John Moutafis
5

Python 2.x.

  1. 'You have %d things.' % things[ 1 ]
  2. 'You have {} things.'.format(things)[ 2 ]

Python 3.6+

  1. 'You have %d things.' % things[ 1 ]
  2. 'You have {} things.'.format(things)[ 2 ]
  3. f'You have {things} things.'[ 3 ]

Referenz

  1. String-Formatierung im printf-Stil
  2. Eingebaute Typen -> str.format
  3. Formatierte String-Literale
ngub05
quelle
Dies fügt der bestehenden Antwort überhaupt nichts hinzu.
Zero Piraeus
3
Und nur weil jemand eine Frage vor mir beantwortet hat, heißt das nicht, dass ich mich ihr mit meiner eigenen Einstellung nähern kann (so wie ich es am besten finde, um die Antwort zu beschreiben). Wenn Sie denken, dass das falsch ist, denke ich, dass das nicht mehr falsch ist, als die Antwort von jemandem herunterzustimmen, weil Sie auch eine Antwort auf dieselbe Frage haben.
ngub05
-1

str.format ()

Eine andere Alternative ist die Verwendung einer str.format()Methode zum Verketten eines Int zu einem String.

In deinem Fall:

Ersetzen

print("You have " + things + " things.")

Mit

print("You have {} things".format(things))

Bonus: für mehrfache Verkettung

Wenn Sie haben

first = 'rohit'
last = 'singh'
age = '5'
print("My Username is {}{}{}".format(first,age,last))
Rohit Singh
quelle