了解了字符串的基本用法之后,我们来看如何定义内容更复杂的字符串内容。如果你用过C,就一定写过下面这种代码:
printf("Hello %s!", "Mars")
在Python里,我们可以用两种类似的形式,完成和C相同的操作。
旧式模板
第一种方式,沿袭了C的风格,像这样:
print("Hello %s!" % "Mars")
其中:
-
"Hello %s!"
仍旧表示字符串模板,其中的%s
叫做format specifier,表示字符串的替代符; - 和C不同的是,在字符串模板后面,我们要写一个
%
作为模板和字符串值的分隔符; - 最后,
"Mars"
是字符串的值;
当然,我们也可以在字符串模板中,包含多个format specifiers,只要我们传递的值的个数和format speicifiers对应即可:
name = "Mars"
print("%s %s" % ("Hello", name))
在上面的代码里,有两点要注意的地方:
- 首先,作为值部分的不仅仅是字面值,也可以是Python变量;
- 其次,当我们使用多个format specifier的时候,值的部分,要通过一个Tuple传递,这和Swift中的Tuple是类似的;
当然,这两个字符串模板的最后的值,都是Hello Mars!。
除了在模板中替换字符串之外,我们还可以替换数字,方法,当然和C也是类似的:
print("PI: %f" % 3.14) # 3.140000
其中,%f
表示浮点数的替代符。但执行一下就会发现,打印出来的结果是3.140000
,多了很多额外的精度,为了去掉它们,我们需要使用额外的format sepcifier:
print("PI: %.2f" % 3.14) # 3.14
其中,.2f
可以理解为小数点后面保留2位的浮点数。这样,就可以得到期望的结果了。
大家可以在这里找到完整的列表。
新式模板
这种旧式模板的一个主要缺陷,是没有为其中的format specifiers提供充分的语义信息。例如,在我们刚才使用的%s %s!
里,我们无法通过它区分,哪个表示action
,哪个表示name
。
为此,Python提供了一个新形式的字符串模板,但是,如果这是你第一次用它,你的感觉估计不会是欣喜,而是觉得有点儿啰嗦:
welcome = {"action": "Hello", "name": "Mars"}
print("%(action)s %(name)s" % welcome)
在上面的例子里可以看到,新的字符串模板仍旧由三部分构成。只不过这次,我们使用了%(action)s
这样的形式,表示“一个表示action的字符串placeholder”这样的概念。
当我们使用这种新式模板的时候,就必须通过一个Dictionary来表示要替换到模板中的值了。其中Dictionary中的key对应着format specifier的名字,而value则对应要替换进去的值。
执行一下,就会发现,值仍旧是Hello Mars!。
看到这,估计你和我的想法类似,这种新式的模板的确没有足够多的动力让你去用它,因为的确有点儿太啰嗦了。于是,Python又对这种新式的模板进行了一些改进,我们还可以这样:
print("{0} {1}!".format("Hello", "Mars"))
这次,我们使用了{0} {1}
这样的形式表示字符串模板,既不用给它起名字,也不用指定的它的类型。只要我们调用format
方法,给它传递和模板中占位符个数相同的内容,这些内容就会被自动替换进去了。
这看起来似乎比C的版本更好一些,但如果你觉得单纯的0 1太抽象,没问题,我们还可以在这种方式里,给占位符单独起名字:
print("{action} {name}!".format(**welcome)) ## Welcome Mars!
只不过这次,我们不仅只能通过Dictionary来设置模板的值,并且,还要通过**welcome
这样的形式,把Dictionary中的值读出来,传递给format
方法。
当然,无论我们怎么折腾,最终打印出来的结果,都是Hello Mars!。
如果你不了解Dictionary,Tuple这些数据类型也没关系,在接下来的内容里,我们会专门提到它们。
网友评论