特殊情况
根据变量数据与字符串一起使用的原因,通用方法可能不合适。
如果您需要准备一个SQL查询
不要使用任何常用的技术来组装字符串。相反,使用SQL库的功能进行参数化查询。
A query is code, so it should not be thought about like normal text. Using the library will make sure that any inserted text is properly escaped. If any part of the query could possibly come from outside the program in any way, that is an opportunity for a malevolent user to perform SQL injection. This is widely considered one of the important computer security problems, costing real companies huge amounts of money every year and causing problems for countless customers. Even if you think you know the data is "safe", there is no real upside to using any other approach.
语法将取决于您正在使用的库,并且超出了这个答案的范围。
如果您需要准备一个URL查询字符串
参见在Python中向给定URL添加参数。不要自己动手;没有任何实际的理由让你的生活更加艰难。
写入文件
虽然可以提前准备一个字符串,但使用单独的.write调用来写入每条数据可能更简单,也更节省内存。当然,在编写之前,非字符串仍然需要转换为字符串,这可能会使代码复杂化。这里没有一个放之四海而皆准的答案,但选择不当通常不会有太大影响。
如果你只是调用打印
内置的print函数接受可变数量的参数,并且可以接受任何对象并使用str对其进行字符串化。在尝试字符串格式化之前,请考虑简单地传递多个参数是否可以达到您的目的。(你也可以使用sep关键字参数来控制参数之间的间距。)
# display a filename, as an example
print('hanning', num, '.pdf', sep='')
当然,对于程序来说,组装字符串是有用的,可能还有其他原因;所以在适当的时候一定要这样做。
需要注意的是,打印是一个特殊情况。唯一以这种方式工作的函数是显式编写为以这种方式工作的函数。对于普通的函数和方法,比如input,或者Matplotlib图的savefig方法,我们需要自己准备一个字符串。
连接
Python支持在两个字符串之间使用+,但不支持在字符串和其他类型之间使用+。为了解决这个问题,我们需要显式地将其他值转换为字符串:'hanning' + str(num) + '.pdf'。
基于模板的方法
解决这个问题的大多数方法都包括使用某种“模板”字符串,其中包含“占位符”,显示应该在哪里添加信息,然后使用一些函数或方法添加缺少的信息。
f-strings
这是在可能的情况下推荐使用的方法。它看起来像f'hanning{num}.pdf'。要插入的变量名直接出现在字符串中。值得注意的是,实际上并没有“f弦”这样的东西;它不是一个单独的类型。相反,Python会提前翻译代码:
>>> 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-string不可能时,这是推荐的方法——主要是因为模板字符串需要提前准备,然后再填充。它看起来像'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})。它不接受关键字参数,而是接受一个映射参数。
That probably doesn't sound very useful - after all, rather than 'hanning{num}.pdf'.format_map(my_dict), we could just as easily write 'hanning{num}.pdf'.format(**my_dict). However, this is useful for mappings that determine values on the fly, rather than ordinary dicts. In these cases, unpacking with ** might not work, because the set of keys might not be determined ahead of time; and trying to unpack keys based on the template is unwieldy (imagine: 'hanning{num}.pdf'.format(num=my_mapping[num]), with a separate argument for each placeholder).
字符串。格式化程序
string标准库模块包含一个很少使用的Formatter类。使用它看起来像string.Formatter().format('hanning{num}.pdf', num=num)。模板字符串再次使用相同的语法。这显然比在字符串上调用.format要笨拙;其动机是允许用户子类化Formatter,为模板字符串定义不同的语法。
以上所有方法都使用一种通用的“格式化语言”(尽管字符串。Formatter允许更改它);还有许多其他东西可以放在{}中。解释它是如何工作的超出了这个答案的范围;请查阅文档。请记住,字面{和}字符需要通过将它们加倍来转义。语法可能是受c#的启发。
%操作符
这是一种解决问题的传统方法,受到C和c++的启发。很长一段时间以来,它一直不被鼓励,但仍然受到支持。对于简单的情况,它看起来像'hanning%s.pdf' % num。正如您所期望的那样,模板中的文字“%”符号需要加倍来转义。
它有一些问题:
It seems like the conversion specifier (the letter after the %) should match the type of whatever is being interpolated, but that's not actually the case. Instead, the value is converted to the specified type, and then to string from there. This isn't normally necessary; converting directly to string works most of the time, and converting to other types first doesn't help most of the rest of the time. So 's' is almost always used (unless you want the repr of the value, using 'r'). Despite that, the conversion specifier is a mandatory part of the syntax.
Tuples are handled specially: passing a tuple on the right-hand side is the way to provide multiple arguments. This is an ugly special case that's necessary because we aren't using function-call syntax. As a result, if you actually want to format a tuple into a single placeholder, it must be wrapped in a 1-tuple.
Other sequence types are not handled specially, and the different behaviour can be a gotcha.
字符串。模板
string标准库模块包含一个很少使用的Template类。实例提供了substitute和safe_substitute方法,它们的工作原理类似于内置的.format (safe_substitute将保留占位符,而不是在参数不匹配时引发异常)。这也应该被认为是解决问题的一种遗留方法。
它看起来像string.Template('hanning$num.pdf').substitute(num=num),受到传统Perl语法的启发。它显然比.format方法更笨拙,因为在方法可用之前必须使用一个单独的类。大括号({})可以在变量名周围使用,以避免歧义。与其他方法类似,模板中的文字'$'需要加倍进行转义。