是否有一个与Ruby的字符串插值等效的Python?


343

Ruby示例:

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

对我而言,成功的Python字符串连接似乎很冗长。


2
这里的问题是name字符串中存在局部变量,在Python中,如果要使用局部变量字典,则必须将其显式传递给字符串格式化程序。
卡特里尔2010年

这不是原始问题,但谢谢。您的评论使我对可变范围有了更好的理解(我仍然对此有所了解)。:)
种姓

1
那么,您对此有何看法? stackoverflow.com/questions/16504732/…–
SalchiPapa


2
有关此确切功能的信息,请参见stackoverflow.com/a/33264516/55721(3.6版
dss539),2016年

Answers:


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 2010年

我了解它的基本要点,但是我不完全理解文档示例中找到的所有其他符号和文本。为什么在此处使用转换为字符串:%(language)s'03d'中的3表示什么?为什么字符串后面有%\?在打印表达式之后分配变量(如果实际上是变量)也会使我感到困惑。抱歉,这很痛苦!
种姓

1
该示例中使用的两种基本格式分别%s是字符串和%03d用前导零填充到3位数字的数字。它可以只是写的print "%s has %03d" % ("Python", 2)。然后,该示例利用将映射关键字放在方括号之后的%方法,该方法是为占位符提供有意义的名称,而不是依赖于其在字符串中的顺序。然后,您传递一个将键名映射到其值的字典。这就是Sven使用该locals()函数返回包含所有局部变量的字典的原因,因此它将映射name到name的值
mikej 2010年

首先让我感到困惑的是,转换类型的必需用法。因此,使用文档术语。%启动说明符。没有(语言)的转换标志,只有转换类型(尾随的“ s”);(数字)具有一个(或两个)转换标志,分别为“ 0”(和“ 3”)。“ d”是转换类型,表示它是整数。我理解正确吗?
种姓

@Caste:是的,基本上是正确的。请注意,您始终s可以将a 用作转换类型-Python可以将几乎所有内容转换为字符串。但是,您当然会失去其他转换类型的特殊格式化功能。
Sven Marnach 2010年


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 2015年

@ d33tah:不,只要在编译时就知道字符串即可。
克莱门特


28

按照PEP 498的规定,Python 3.6包含字符串插值。您将可以执行以下操作:

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

请注意,我讨厌海绵宝宝,所以写这篇文章有点痛苦。:)


那个海绵宝宝参考(/ disaste)的想法:现在得投票支持。
javadba


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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.