Есть ли Python, эквивалентный строковой интерполяции Ruby?

343

Пример Ruby:

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

Успешная конкатенация строк Python кажется мне многословной.

каста
источник
2
Проблема здесь в том, что nameв строке лежит локальная переменная, а в Python вы должны явно передавать словарь локальных переменных в формататор строк, если вы хотите, чтобы они их использовали.
Катриэль
Это была не оригинальная проблема, но спасибо. Ваш комментарий дал мне немного лучшее понимание области видимости (с чем я все еще справляюсь). :)
Каста
1
Что вы думаете об этом, тогда? stackoverflow.com/questions/16504732/…
SalchiPapa
2
См. Stackoverflow.com/a/33264516/55721 для этой точной функции в 3.6
dss539

Ответы:

413

В Python 3.6 будет добавлена интерполяция буквенных строк, аналогичная интерполяции строк в Ruby. Начиная с этой версии Python (выпуск которой запланирован на конец 2016 года), вы сможете включать выражения в "f-strings", например:

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

До 3.6 самый близкий к этому

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

%Оператор может быть использован для интерполяции строк в Python. Первый операнд - это строка для интерполяции, второй может иметь разные типы, включая «отображение», отображение имен полей на значения, которые должны быть интерполированы. Здесь я использовал словарь локальных переменных locals()для сопоставления имени поляname с его значением в качестве локальной переменной.

Тот же код, использующий .format()метод последних версий Python, будет выглядеть так:

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

Также есть string.Templateкласс:

tmpl = string.Template("Who lives in a Pineapple under the sea? $name.")
print(tmpl.substitute(name="Spongebob Squarepants"))
Свен Марнах
источник
@Caste см. Здесь: docs.python.org/library/stdtypes.html#string-formatting и оставьте дополнительный комментарий, если вам нужна дополнительная информация
mikej
Я понимаю основную суть этого, однако я не полностью понимаю все дополнительные символы и текст, найденные в примере в документации. Почему здесь используется функция преобразования в строку:% (language) s Что означают 3 в «03d»? Почему после строки есть% \? Присвоение переменных (если они фактически являются переменными) после выражения print меня также смущает. Извините, если это боль!
Каста
1
В этом примере используются два основных формата %sдля строки и %03dдля числа, дополненного до 3 цифр начальными нулями. Это может быть просто написано print "%s has %03d" % ("Python", 2). Затем в этом примере в скобках %ставится ключ сопоставления, после которого указывается значащие имена заполнителей, а не полагается на их порядок в строке. Затем вы передаете словарь, который сопоставляет имена ключей с их значениями. Вот почему Свен использует locals()функцию, которая возвращает dict, содержащий все ваши локальные переменные, поэтому он сопоставляется nameсо значением name
mikej
Сначала меня смутило обязательное использование типа конверсии. Итак, используя терминологию документации. % Запускает спецификатор. Для (языка) нет флага конверсии, только тип конверсии (завершающий 's'); (число), однако, имеет один (или два) флага преобразования, который равен '0' (и '3' соответственно). «D» является типом преобразования и означает, что это целое число. Правильно ли я понял?
Каста
@ Каста: Да, это в принципе правильно. Обратите внимание, что вы всегда можете использовать sв качестве типа преобразования - Python может преобразовать практически что угодно в строку. Но, конечно, вы потеряете специальные возможности форматирования других типов преобразования.
Свен Марнах
143

Начиная с Python 2.6.X вы можете использовать:

"my {0} string: {1}".format("cool", "Hello there!")
EinLama
источник
27
Обратите внимание, что %оператор для интерполяции строк не рекомендуется в Python 3.x. docs.python.org/dev/py3k/whatsnew/… объявляет о планах отказаться от %начиная с версии 3.1, но этого не произошло.
Свен Марнач
8
% -синтаксис все еще живет в Python 3 (не рекомендуется в Python 3.2)
Кори Голдберг
9
Просто примечание: номер в {}может меня исключить.
ничья
32

Я разработал пакет interpy , который позволяет интерполировать строки в Python .

Просто установите его через pip install interpy. А затем добавьте строку# coding: interpy в начале ваших файлов!

Пример:

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

name = "Spongebob Squarepants"
print "Who lives in a Pineapple under the sea? \n#{name}."
Сырус Акбары Ньето
источник
3
Это кажется действительно небезопасным.
d33tah
@ d33tah: Нет, пока строки известны во время компиляции.
Климент
28

Строковая интерполяция Python похожа на printf () в C

Если вы попытаетесь:

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

Тег %sбудет заменен на nameпеременную. Вы должны взглянуть на теги функции печати: http://docs.python.org/library/functions.html

Oleiade
источник
1
Как я могу сделать это с 2 переменными?
Хулио Маринс
16
@JulioMarins Используйте кортеж: print "First is %s, second is %s" % (var1, var2).
kirbyfan64sos
28

Строковая интерполяция будет включена в Python 3.6, как указано в PEP 498 . Вы сможете сделать это:

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

Обратите внимание, что я ненавижу Спанч Боба, поэтому писать это было немного больно. :)

kirbyfan64sos
источник
Спасибо за эту ссылку Спанч Боба (/ distaste): сейчас надо это сказать.
Джавадба
4

Вы также можете иметь это

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
источник
Я не верю, что ОП предназначено #для печати. Они просто используют синтаксис Ruby.
Jaynp
Ты прав. Я отредактировал ответ. Я не знаком с Руби, поэтому думал, что #персонаж будет напечатан.
Цюань до
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)

Использование:

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: производительность может быть проблемой. Это полезно для локальных сценариев, а не для рабочих журналов.

Дублированный:

Пауло Чек
источник
2

Для старого Python (проверено на 2.4) верхнее решение указывает путь. Ты можешь сделать это:

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

И вы получаете

d: 1 f: 1.1 s: s
Майкл Фокс
источник