提问人:Gish 提问时间:6/3/2010 最后编辑:Karl KnechtelGish 更新时间:5/24/2023 访问量:1183783
如何将变量的值放入字符串中(将其插值到字符串中)?
How do I put a variable’s value inside a string (interpolate it into the string)?
问:
我想把一个 .这是我目前正在做的事情:int
string
num = 40
plot.savefig('hanning40.pdf') #problem line
我必须为几个不同的数字运行程序,所以我想做一个循环。但是像这样插入变量是行不通的:
plot.savefig('hanning', num, '.pdf')
如何在 Python 字符串中插入变量?
另请参阅
如果您尝试创建文件路径,请参阅如何从部件创建文件的完整路径(例如文件夹的路径、名称和扩展名)?以获取其他技术。通常最好使用特定于创建路径的代码。
如果您尝试使用可变数据组合 URL,请不要使用普通的字符串格式,因为它容易出错,而且比必要的更困难。提供专用工具。请参阅在 Python 中向给定 URL 添加参数。
如果尝试组合 SQL 查询,请不要使用普通的字符串格式,因为这是一个重大的安全风险。这就是“SQL注入”的原因,每年都会花费大量资金。例如,请参阅如何在 Python 的 SQL 语句中使用变量?
如果只想打印(输出)字符串,可以先以这种方式准备它,或者如果不需要字符串进行任何其他操作,请使用单个调用来打印
输出的每一部分。请参阅如何在同一行上同时打印多个内容(固定文本和/或变量值?),了解这两种方法的详细信息。
答:
plot.savefig('hanning(%d).pdf' % num)
运算符在字符串后面时,允许您通过格式代码(在本例中为 )将值插入到该字符串中。有关详细信息,请参阅 Python 文档:%
%d
评论
%
.format()
%
您可以用作普通的字符串连接函数,也可以用作 .+
str()
"hello " + str(10) + " world" == "hello 10 world"
评论
+
通常,您可以使用以下方法创建字符串:
stringExample = "someString " + str(someNumber)
print(stringExample)
plot.savefig(stringExample)
使用 f 字符串:
plot.savefig(f'hanning{num}.pdf')
这是在 3.6 中添加的,是新的首选方式。
使用 str.format()
:
plot.savefig('hanning{0}.pdf'.format(num))
字符串连接:
plot.savefig('hanning' + str(num) + '.pdf')
plot.savefig('hanning%s.pdf' % num)
使用局部变量名称(巧妙的技巧):
plot.savefig('hanning%(num)s.pdf' % locals())
使用字符串。模板
:
plot.savefig(string.Template('hanning${num}.pdf').substitute(locals()))
另请参阅:
评论
'foo %d, bar %d' % (foo, bar)
plot.savefig('hanning{num}s.pdf'.format(**locals()))
.format
我需要一个扩展版本:我需要生成一系列形式的文件名,而不是在字符串中嵌入单个数字,而不是“file1.pdf”,“file2.pdf”等格式。这是它的工作原理:
['file' + str(i) + '.pdf' for i in range(1,4)]
评论
str()
f'file{i}.pdf'
随着 Python 3.6 中格式化字符串文字(简称“f-strings”)的引入,现在可以用更简短的语法来编写它:
>>> name = "Fred"
>>> f"He said his name is {name}."
'He said his name is Fred.'
使用问题中给出的示例,它看起来像这样
plot.savefig(f'hanning{num}.pdf')
评论
如果你想在字符串中放入多个值,你可以利用format
nums = [1,2,3]
plot.savefig('hanning{0}{1}{2}.pdf'.format(*nums))
将导致字符串 .这可以用任何数组来完成。hanning123.pdf
您可以在字符串中创建 dict 和替换变量。
var = {"name": "Abdul Jalil", "age": 22}
temp_string = "My name is %(name)s. I am %(age)s years old." % var
特殊情况
根据变量数据与字符串一起使用的原因,通用方法可能不合适。
如果需要准备 SQL 查询
不要使用任何常用的技术来组装琴弦。相反,请使用 SQL 库的功能进行参数化查询。
查询是代码,因此不应将其视为普通文本。使用该库将确保正确转义任何插入的文本。如果查询的任何部分可能以任何方式来自程序外部,则这是恶意用户执行 SQL 注入的机会。这被广泛认为是重要的计算机安全问题之一,每年都会花费大量资金给实体公司带来麻烦,并给无数客户带来问题。即使您认为自己知道数据是“安全的”,使用任何其他方法也没有真正的好处。
语法将取决于您使用的库,并且超出了本答案的范围。
如果需要准备 URL 查询字符串
请参阅在 Python 中向给定 URL 添加参数。不要自己动手;没有实际的理由让你的生活更艰难。
写入文件
虽然可以提前准备字符串,但使用单独的调用写入每条数据可能更简单、更节省内存。当然,在编写之前,非字符串仍然需要转换为字符串,这可能会使代码复杂化。这里没有一个放之四海而皆准的答案,但选择不当通常并不重要。.write
如果您只是打电话print
内置函数接受可变数量的参数,并且可以接受任何对象并使用 将其字符串化。在尝试字符串格式设置之前,请考虑是否只需传递多个参数即可实现所需的效果。(还可以使用关键字参数来控制参数之间的间距。print
str
sep
# display a filename, as an example
print('hanning', num, '.pdf', sep='')
当然,可能还有其他原因可以解释为什么程序组装字符串很有用;因此,请务必在适当的情况下这样做。
需要注意的是,这是一个特例。唯一以这种方式工作的函数是显式编写为以这种方式工作的函数。对于普通的函数和方法,比如 ,或者 Matplotlib 图的方法,我们需要自己准备一个字符串。print
input
savefig
串联
Python 支持在两个字符串之间使用,但不支持在字符串和其他类型之间使用。要解决这个问题,我们需要将其他值显式转换为字符串: 。+
'hanning' + str(num) + '.pdf'
基于模板的方法
解决问题的大多数方法都涉及某种“模板”字符串,其中包含显示应添加信息的位置的“占位符”,然后使用某些函数或方法来添加缺失的信息。
F 弦
如果可能,这是推荐的方法。它看起来像.要插入的变量的名称直接显示在字符串中。需要注意的是,实际上并不存在“f-string”这样的东西;它不是一个单独的类型。相反,Python 将提前翻译代码:f'hanning{num}.pdf'
>>> def example(num):
... return f'hanning{num}.pdf'
...
>>> import dis
>>> dis.dis(example)
2 0 LOAD_CONST 1 ('hanning')
2 LOAD_FAST 0 (num)
4 FORMAT_VALUE 0
6 LOAD_CONST 2 ('.pdf')
8 BUILD_STRING 3
10 RETURN_VALUE
因为它是一种特殊语法,所以它可以访问其他方法中未使用的操作码。
str.format
当 f 字符串不可行时,建议使用这种方法 - 主要是因为模板字符串需要提前准备好并在以后填写。它看起来像 或 。这里,是内置于字符串中的方法,它可以按位置或关键字接受参数。'hanning{}.pdf'.format(num)
'hanning{num}.pdf'.format(num=num)'
format
特别是对于 ,了解内置的 和 函数返回将变量名称映射到这些变量内容的字典很有用。因此,我们可以使用类似 的东西,而不是像 ,解开字典。str.format
locals
globals
vars
'{a}{b}{c}'.format(a=a, b=b, c=c)
'{a}{b}{c}'.format(**locals())
locals()
str.format_map
这是 的罕见变体。它看起来像.它不接受关键字参数,而是接受单个参数,即映射。.format
'hanning{num}.pdf'.format_map({'num': num})
这听起来可能不是很有用 - 毕竟,我们可以很容易地写出 .但是,这对于动态确定值的映射很有用,而不是普通的 s。在这些情况下,解包可能不起作用,因为可能无法提前确定密钥集;并且尝试根据模板解压缩密钥是笨拙的(想象一下:,每个占位符都有一个单独的参数)。'hanning{num}.pdf'.format_map(my_dict)
'hanning{num}.pdf'.format(**my_dict)
dict
**
'hanning{num}.pdf'.format(num=my_mapping[num])
string.Formatter
标准库模块包含一个很少使用的类。使用它看起来像 .模板字符串再次使用相同的语法。这显然比仅仅调用字符串更笨拙;其动机是允许用户子类化,以便为模板字符串定义不同的语法。string
Formatter
string.Formatter().format('hanning{num}.pdf', num=num)
.format
Formatter
上述所有方法都使用一种通用的“格式化语言”(尽管允许更改它);还有很多其他的东西可以放在里面。解释它是如何工作的超出了这个答案的范围;请查阅文档。请记住,文字和字符需要通过加倍来转义。该语法可能受到 C# 的启发。string.Formatter
{}
{
}
运营商%
这是解决问题的传统方法,受 C 和 C++ 的启发。长期以来,人们一直不鼓励这样做,但仍然受到支持。对于简单的情况,它看起来像。如您所料,模板中的文字符号需要加倍才能转义它们。'hanning%s.pdf' % num
'%'
它有一些问题:
似乎转换说明符()后面的字母应该与要插值的任何内容的类型匹配,但事实并非如此。相反,该值将转换为指定的类型,然后从那里转换为字符串。这通常不是必需的;大多数情况下,直接转换为字符串是有效的,而首先转换为其他类型在其余时间的大部分时间里都无济于事。所以几乎总是被使用(除非你想要值,使用 )。尽管如此,转换说明符是语法的强制性部分。
%
's'
repr
'r'
元组是专门处理的:在右侧传递元组是提供多个参数的方法。这是一个丑陋的特例,这是必要的,因为我们没有使用函数调用语法。因此,如果实际上要将元组格式化为单个占位符,则必须将其包装在 1 元组中。
其他序列类型没有经过特殊处理,不同的行为可能是一个问题。
string.Template
标准库模块包含一个很少使用的类。实例提供的工作方式与内置方法类似(将保持占位符不变,而不是在参数不匹配时引发异常)。这也应被视为解决问题的遗留方法。string
Template
substitute
safe_substitute
.format
safe_substitute
它看起来像 ,并且受到传统 Perl 语法的启发。它显然比方法更笨拙,因为在方法可用之前必须使用单独的类。可以选择在变量名称周围使用大括号 (),以避免歧义。与其他方法类似,模板中的文字需要加倍才能进行转义。string.Template('hanning$num.pdf').substitute(num=num)
.format
{}
'$'
评论