Gibt es ein Python, das Rubys String-Interpolation entspricht?

343

Ruby Beispiel:

name = "Spongebob Squarepants"
puts "Who lives in a Pineapple under the sea? \n#{name}."

Die erfolgreiche Verkettung von Python-Strings scheint mir ausführlich zu sein.

Kaste
quelle
2
Das Problem hierbei ist, dass namees sich um eine lokale Variable handelt, die in der Zeichenfolge liegt. In Python müssen Sie das Wörterbuch der lokalen Variablen explizit an den Zeichenfolgenformatierer übergeben, wenn Sie diese verwenden möchten.
Katriel
Dies war nicht die ursprüngliche Ausgabe, aber danke. Ihr Kommentar gab mir ein etwas besseres Verständnis des variablen Umfangs (etwas, mit dem ich immer noch an Boden gewinne). :)
Kaste
1
Was denkst du dann über diesen? stackoverflow.com/questions/16504732/…
SalchiPapa
2
Siehe stackoverflow.com/a/33264516/55721 für diese genaue Funktion in 3.6
dss539

Antworten:

413

Python 3.6 fügt eine Literal-String-Interpolation hinzu , die der Ruby-String-Interpolation ähnelt. Ab dieser Version von Python (die voraussichtlich Ende 2016 veröffentlicht wird) können Sie Ausdrücke in "f-Strings" einfügen, z

name = "Spongebob Squarepants"
print(f"Who lives in a Pineapple under the sea? {name}.")

Vor 3.6 können Sie dem am nächsten kommen

name = "Spongebob Squarepants"
print("Who lives in a Pineapple under the sea? %(name)s." % locals())

Der %Operator kann für die Zeichenfolgeninterpolation in Python verwendet werden. Der erste Operand ist die zu interpolierende Zeichenfolge, der zweite kann verschiedene Typen haben, einschließlich einer "Zuordnung", wobei Feldnamen den zu interpolierenden Werten zugeordnet werden. Hier habe ich das Wörterbuch der lokalen Variablen verwendet locals(), um den Feldnamen nameseinem Wert als lokale Variable zuzuordnen .

Der gleiche Code, der die .format()Methode der letzten Python-Versionen verwendet, würde folgendermaßen aussehen:

name = "Spongebob Squarepants"
print("Who lives in a Pineapple under the sea? {name!s}.".format(**locals()))

Es gibt auch die string.TemplateKlasse:

tmpl = string.Template("Who lives in a Pineapple under the sea? $name.")
print(tmpl.substitute(name="Spongebob Squarepants"))
Sven Marnach
quelle
@Caste siehe hier: docs.python.org/library/stdtypes.html#string-formatting und poste einen Folgekommentar, wenn du weitere Details
benötigst
Ich verstehe das Wesentliche, verstehe jedoch nicht alle zusätzlichen Symbole und Texte, die im Beispiel in der Dokumentation enthalten sind. Warum hier die Verwendung von in Zeichenfolge konvertieren:% (Sprache) s Was bedeutet die 3 in '03d'? Warum gibt es nach der Zeichenfolge% \? Die Zuweisung von Variablen (wenn es sich tatsächlich um Variablen handelt) nach dem Druckausdruck verwirrt mich ebenfalls. Entschuldigung, wenn dies ein Schmerz ist!
Kaste
1
Die beiden im Beispiel verwendeten Grundformate gelten %sfür eine Zeichenfolge und %03dfür eine auf 3 Ziffern aufgefüllte Zahl mit führenden Nullen. Es könnte einfach geschrieben werden print "%s has %03d" % ("Python", 2). In diesem Beispiel wird dann ein Zuordnungsschlüssel in Klammern gesetzt %, um den Platzhaltern aussagekräftige Namen zu geben, anstatt sich auf ihre Reihenfolge in der Zeichenfolge zu verlassen. Anschließend übergeben Sie ein Wörterbuch, das die Schlüsselnamen ihren Werten zuordnet. Aus diesem Grund verwendet Sven die locals()Funktion, die ein Diktat zurückgibt, das alle Ihre lokalen Variablen enthält, damit es namedem Wert von name zugeordnet wird
mikej
Die erforderliche Verwendung eines Konvertierungstyps hat mich zuerst verwirrt. Verwenden Sie also die Dokumentationsterminologie. Das% startet den Bezeichner. Es gibt kein Konvertierungsflag für (Sprache), nur einen Konvertierungstyp (das nachfolgende 's'); (Nummer) hat jedoch ein (oder zwei) Konvertierungsflags, die '0' (bzw. '3') sind. Das 'd' ist der Konvertierungstyp und bedeutet, dass es sich um eine Ganzzahl handelt. Habe ich richtig verstanden
Kaste
@Caste: Ja, das ist im Grunde richtig. Beachten Sie, dass Sie immer einen sals Konvertierungstyp verwenden können - Python kann fast alles in einen String konvertieren. Aber natürlich würden Sie die speziellen Formatierungsfunktionen anderer Konvertierungstypen verlieren.
Sven Marnach
143

Seit Python 2.6.X möchten Sie möglicherweise Folgendes verwenden:

"my {0} string: {1}".format("cool", "Hello there!")
EinLama
quelle
27
Beachten Sie, dass der %Operator für die Zeichenfolgeninterpolation in Python 3.x nicht veraltet ist. docs.python.org/dev/py3k/whatsnew/… kündigt den Plan an, %ab 3.1 zu verwerfen , aber dies ist nie geschehen.
Sven Marnach
8
% -Ssyntax lebt noch in Python 3 (nicht veraltet ab Python 3.2)
Corey Goldberg
9
Nur eine Anmerkung: Die Nummer in {}kann ich eliminieren.
Unentschieden
32

Ich habe das Interpy- Paket entwickelt, das die String-Interpolation in Python ermöglicht .

Installieren Sie es einfach über pip install interpy. Fügen Sie dann die Zeile # coding: interpyam Anfang Ihrer Dateien hinzu!

Beispiel:

#!/usr/bin/env python
# coding: interpy

name = "Spongebob Squarepants"
print "Who lives in a Pineapple under the sea? \n#{name}."
Syrus Akbary Nieto
quelle
3
Das scheint wirklich unsicher zu sein.
d33tah
@ d33tah: Nein, solange die Zeichenfolgen zur Kompilierungszeit bekannt sind.
Clément
28

Die String-Interpolation von Python ähnelt der von printf ()

Wenn du es versuchst:

name = "SpongeBob Squarepants"
print "Who lives in a Pineapple under the sea? %s" % name

Das Tag %swird durch die nameVariable ersetzt. Sie sollten sich die Druckfunktions-Tags ansehen: http://docs.python.org/library/functions.html

Oleiade
quelle
1
Wie kann ich das mit 2 Variablen machen?
Julio Marins
16
@ JulioMarins Verwenden Sie ein Tupel : print "First is %s, second is %s" % (var1, var2).
kirbyfan64sos
28

Die String-Interpolation wird in Python 3.6 enthalten sein, wie in PEP 498 angegeben . Sie können dies tun:

name = 'Spongebob Squarepants'
print(f'Who lives in a Pineapple under the sea? \n{name}')

Beachten Sie, dass ich SpongeBob hasse, daher war das Schreiben etwas schmerzhaft. :) :)

kirbyfan64sos
quelle
Danke für diese SpongeBob-Referenz (/ Abneigung): Ich muss das jetzt positiv bewerten.
Javadba
4

Sie können dies auch haben

name = "Spongebob Squarepants"
print "Who lives in a Pineapple under the sea? \n{name}.".format(name=name)

http://docs.python.org/2/library/string.html#formatstrings

Quan To
quelle
Ich glaube nicht, dass OP beabsichtigt hat, das #zu drucken. Sie verwenden nur die Ruby-Syntax.
Jaynp
Du hast recht. Ich habe die Antwort bearbeitet. Ich bin mit Ruby nicht vertraut, daher dachte ich, dass das #Zeichen gedruckt werden würde.
Quan bis
3
import inspect
def s(template, **kwargs):
    "Usage: s(string, **locals())"
    if not kwargs:
        frame = inspect.currentframe()
        try:
            kwargs = frame.f_back.f_locals
        finally:
            del frame
        if not kwargs:
            kwargs = globals()
    return template.format(**kwargs)

Verwendungszweck:

a = 123
s('{a}', locals()) # print '123'
s('{a}') # it is equal to the above statement: print '123'
s('{b}') # raise an KeyError: b variable not found

PS: Leistung kann ein Problem sein. Dies ist nützlich für lokale Skripte, nicht für Produktionsprotokolle.

Dupliziert:

Paulo Check
quelle
2

Für altes Python (getestet auf 2.4) weist die Top-Lösung den Weg. Du kannst das:

import string

def try_interp():
    d = 1
    f = 1.1
    s = "s"
    print string.Template("d: $d f: $f s: $s").substitute(**locals())

try_interp()

Und du verstehst

d: 1 f: 1.1 s: s
Michael Fox
quelle