Python 字符串格式化详解:从古老到现代的演进与精通
字符串是 Python 中最常用的数据类型之一,而将变量、表达式或其他值嵌入到字符串中,构建出具有特定结构的文本,则是编程中的常见任务。这个过程被称为“字符串格式化”。Python 提供了多种强大的字符串格式化方法,随着语言的发展,这些方法也在不断演进,提供了更加灵活、易读和高效的选项。
本文将深入探讨 Python 中各种字符串格式化技术,从早期的方法到现代的最佳实践,详细讲解它们的用法、特性以及底层的格式化规范迷你语言,帮助你全面掌握 Python 的字符串格式化艺术。
为什么需要字符串格式化?
想象一下,你需要输出一段包含动态信息(如用户名、分数、日期)的文本。最原始的方法可能是简单地使用字符串连接:
python
name = "Alice"
score = 95
message = "Hello, " + name + "! Your score is " + str(score) + "."
print(message)
这种方法在处理少量、类型一致的数据时尚可接受,但很快就会暴露出问题:
- 可读性差: 当需要连接的变量很多时,代码会变得冗长且难以阅读,字符串和变量交织在一起,难以分辨。
- 类型限制: 只能连接字符串类型。如果连接的不是字符串,需要手动进行类型转换(如
str(score)
),增加了代码的复杂性和出错的可能性。 - 格式控制困难: 难以控制数值的显示格式(如小数点位数、千位分隔符、对齐方式),需要额外的字符串操作函数。
字符串格式化技术应运而生,旨在解决这些问题,提供一种更清晰、更灵活、更强大的方式来构建动态字符串。
演进之路:Python 字符串格式化方法
Python 历史上主要经历了以下几种字符串格式化方法:
- %-formatting (百分号格式化): 借鉴了 C 语言的
printf
风格,是 Python 早期版本主要使用的格式化方法。 str.format()
方法: 在 Python 2.6 引入,是比 %-formatting 更灵活、更强大的替代方案,推荐在 Python 2.x 和 3.x 中使用(在 f-strings 出现之前)。- f-strings (格式化字符串字面量): 在 Python 3.6 引入,是目前最推荐和最受欢迎的格式化方法,提供了极高的可读性和性能。
- Template Strings (模板字符串): 适用于更简单的替换场景,特别是处理用户提供的字符串模板时,提供了一定的安全性。
我们将逐一详细介绍这些方法。
1. %-formatting (百分号格式化)
%-formatting 是 Python 最古老的字符串格式化方法,其语法类似于 C 语言的 sprintf
函数。它使用百分号 %
作为特殊标记,后跟一个格式说明符(specifier),用于指定如何格式化对应位置的值。
基本语法:
python
"格式字符串" % (值1, 值2, ...)
如果只有一个值,圆括号可以省略:
python
"格式字符串" % 值
格式说明符的通用形式为:
%[(name)][flags][width][.precision]type
(name)
: 可选。如果格式字符串左侧是字典,可以使用键名来指定要格式化的值。flags
: 可选。用于控制格式化的一些特殊行为(如符号、零填充、对齐等)。常见的 flags 包括:-
: 左对齐。默认是右对齐。+
: 对于正数,总是在前面加上+
符号。对于负数,总是加上-
符号。(空格): 对于正数,在前面留一个空格。对于负数,在前面加上
-
符号。当+
和同时出现时,
+
优先。0
: 使用零进行填充,而不是空格。当同时指定了 width 时有效。如果指定了-
flag,0
flag 会被忽略。#
: 交替形式。对于整数类型,%#o
会在八进制数前加上0o
,%#x
或%#X
会在十六进制数前加上0x
或0X
。对于浮点数,总是包含小数点,即使后面没有数字。对于g
或G
类型,保留末尾的零。
width
: 可选。指定格式化后字段的最小宽度。如果值不足指定宽度,会根据对齐方式进行填充。.precision
: 可选。- 对于浮点数 (
f
,e
,E
,g
,G
,%
):指定小数点后显示的位数(对于g
和G
,指定总有效数字位数)。 - 对于字符串 (
s
):指定输出的最大字符数。
- 对于浮点数 (
type
: 必需。 指定要格式化的值的类型以及如何表示它。常见的 type 包括:s
: 字符串 (使用str()
进行转换)。r
: 字符串 (使用repr()
进行转换)。c
: 单个字符 (接受一个整数或单个字符的字符串)。d
: 带符号的十进制整数。i
: 带符号的十进制整数 (与d
相同)。o
: 无符号八进制整数。x
: 无符号十六进制整数 (小写)。X
: 无符号十六进制整数 (大写)。e
: 浮点数 (科学计数法,小写e
)。E
: 浮点数 (科学计数法,大写E
)。f
: 浮点数 (定点表示法)。F
: 浮点数 (定点表示法,与f
相同,但在特殊值(如 NaN, Inf)上可能不同)。g
: 浮点数 (通用格式)。根据数值大小,自动选择e
或f
格式中更简洁的一种。精度指定的是总有效数字位数。G
: 浮点数 (通用格式),使用E
或F
。%
: 字面量的 ‘%’ 字符 (不需要对应的值)。
示例:
“`python
基本用法
name = “Bob”
age = 30
print(“My name is %s and I am %d years old.” % (name, age))
浮点数精度和宽度
pi = 3.14159265
print(“Pi is approximately %.2f” % pi) # 精度:保留小数点后2位
print(“Pi is approximately %8.4f” % pi) # 宽度8,精度4
整数格式化 (十六进制, 零填充)
number = 255
print(“Decimal: %d, Hex: %x, Hex (uppercase): %X” % (number, number, number))
print(“Zero-padded decimal: %05d” % number) # 宽度5,零填充
对齐
text = “Python”
print(“Left aligned: %-10s” % text) # 左对齐,宽度10
print(“Right aligned: %10s” % text) # 右对齐,宽度10 (默认)
符号和交替形式
pos_num = 100
neg_num = -50
print(“Positive: %+d, Negative: %+d” % (pos_num, neg_num)) # 显示符号
print(“Space for positive: % d” % pos_num) # 正数留空
print(“Hex with prefix: %#x” % 255) # 16进制加前缀 0x
使用字典映射 (通过名称引用)
data = {‘name’: ‘Charlie’, ‘score’: 88}
print(“Student %(name)s scored %(score)d points.” % data)
字面量百分号
print(“Progress: 80%% done.”)
“`
%-formatting 的优缺点:
- 优点:
- 语法简洁(对于简单场景)。
- 在 C 语言背景的开发者中很熟悉。
- 性能尚可(尤其是在早期 Python 版本)。
- 缺点:
- 可读性差: 当需要格式化的值很多时,格式字符串会变得很长,并且格式说明符与后面的值列表的位置对应关系不直观,容易出错。
- 类型不安全: 如果提供的值类型与格式说明符不匹配,会在运行时抛出
TypeError
。 - 灵活性差: 难以重用同一个值,必须在值列表中重复提供。索引或命名引用不如后续方法灵活。
- 不能方便地嵌入表达式。
由于上述缺点,特别是可读性和类型不安全问题,%-formatting 在现代 Python 中通常不推荐作为首选方法,除非是维护遗留代码。
2. str.format()
方法
str.format()
方法是 Python 2.6 引入的一种新的字符串格式化方式,旨在改进 %-formatting 的不足。它通过在字符串中使用 {}
作为占位符,然后在调用 .format()
方法时提供要填充的值。
基本语法:
python
"格式字符串中包含{}".format(值1, 值2, ...)
"格式字符串中包含{key}".format(key=值, ...)
"格式字符串中包含{index}".format(值0, 值1, ...)
在 {}
占位符中,可以包含:
- 空
{}
:按顺序填充format()
方法的参数。 - 基于位置的索引
{0}
,{1}
等:根据索引填充format()
方法的参数。可以重复使用索引。 - 基于名称的键
{name}
,{age}
等:根据名称填充format()
方法的关键字参数。
占位符 {}
内部可以包含更详细的格式说明,其通用形式为:
{field_name!conversion:format_spec}
field_name
: 可选。可以是变量名(用于关键字参数)或位置索引(用于位置参数)。如果省略,则按顺序使用位置参数。!conversion
: 可选。指定在格式化之前如何将值转换为字符串。!s
: 使用str()
进行转换 (默认)。!r
: 使用repr()
进行转换。!a
: 使用ascii()
进行转换。
format_spec
: 可选。这是.format()
方法的核心格式控制部分,与 %-formatting 的格式说明符类似,但语法和功能更强大。它跟在冒号:
后面。
Format Specification Mini-Language (格式规范迷你语言)
format_spec
的语法结构为:
[[fill]align][sign][#][0][width][grouping_option][.precision][type]
[fill]align
: 对齐和填充。fill
是用于填充的单个字符(默认为空格)。align
指定对齐方式:<
: 左对齐 (默认用于字符串)。>
: 右对齐 (默认用于数字)。=
: 填充字符放在符号和数字之间 (只对数字类型有效)。^
: 居中对齐。
sign
: 符号控制 (只对数字类型有效):+
: 对正数和负数都显示符号。-
: 只对负数显示符号 (默认)。(空格): 对正数显示空格,对负数显示负号。
#
: 交替形式。与 %-formatting 类似,用于添加前缀 (0o
,0x
,0X
) 或强制显示小数点。0
: 零填充 (只对数字有效)。类似于%0
,但可以与width
结合使用,并且可以与align
结合 (=
)。width
: 最小字段宽度。grouping_option
: 数字分组。,
: 使用逗号作为千位分隔符。_
: 使用下划线作为千位分隔符 (PEP 515)。
.precision
: 精度。- 对于浮点类型 (
f
,e
,E
,g
,G
,%
):小数点后显示的位数。 - 对于非数字类型 (
s
):最大字段宽度 (字符串截断)。
- 对于浮点类型 (
type
: 类型。与 %-formatting 类似,但有一些差异和新增类型:s
: 字符串。None
: 与s
相同 (默认用于非数字)。d
: 十进制整数。b
: 二进制整数。o
: 八进制整数。x
: 十六进制整数 (小写)。X
: 十六进制整数 (大写)。c
: 字符。e
,E
: 科学计数法浮点数。f
,F
: 定点表示法浮点数。g
,G
: 通用格式浮点数。%
: 将数字乘以 100 并显示为百分数 (f
格式,带百分号)。n
: 数字。根据当前 locale 设置格式化数字 (例如,千位分隔符和小数点)。
示例:
“`python
基本用法 (按顺序)
print(“Hello, {}! You are {} years old.”.format(“Alice”, 30))
使用位置索引
print(“The order is {1}, {0}, {1}.”.format(“apple”, “banana”))
使用名称
print(“Student {name} scored {score} points.”.format(name=”Charlie”, score=88))
混合使用位置和名称 (位置参数必须在关键字参数之前)
print(“Item {0}: {item_name}, Price: {1:.2f}”.format(1, 19.99, item_name=”Book”))
访问对象属性或字典元素
class Person:
def init(self, name, age):
self.name = name
self.age = age
p = Person(“David”, 25)
data = {‘city’: ‘London’, ‘temp’: 15.5}
print(“Person: {0.name} is {0.age} years old.”.format(p))
print(“Weather in {city}: {temp} degrees.”.format(**data)) # 使用 ** 展开字典作为关键字参数
格式规范 mini-language 示例
value = 12345.6789
宽度和对齐
print(“Width 10, right align (default for numbers): {:10}”.format(value))
print(“Width 10, left align: {:<10}”.format(value))
print(“Width 10, center align: {:^10}”.format(value))
print(“Width 10, center align with fill: {:-^10}”.format(value))
精度
print(“Precision 2 (for float): {:.2f}”.format(value))
print(“Precision 4 (total effective for g): {:.4g}”.format(value))
print(“Precision 5 (for string): {:.5s}”.format(“HelloWorld”)) # 截断字符串
数字类型和进制
num = 255
print(“Decimal: {:d}, Binary: {:b}, Octal: {:o}, Hex: {:x}”.format(num, num, num, num))
print(“Hex uppercase: {:X}”.format(num))
print(“Character: {:c}”.format(65)) # ASCII code for ‘A’
符号
print(“Positive with sign: {:+d}”.format(100))
print(“Negative with sign: {:+d}”.format(-100))
print(“Positive with space: {: d}”.format(100))
print(“Negative with space: {: d}”.format(-100))
零填充和填充在符号后
print(“Zero-padded width 8: {:08d}”.format(123))
print(“Zero-padded with sign after zero: {:0=+8d}”.format(123))
print(“Zero-padded with sign after zero: {:0=+8d}”.format(-123))
交替形式 (#)
print(“Hex with prefix: {:#x}”.format(num))
print(“Float with forced decimal point: {:#.0f}”.format(123))
print(“Float with trailing zeros (g): {:#g}”.format(10.0))
数字分组 (千位分隔符)
big_number = 1234567890
print(“With comma separator: {:,d}”.format(big_number))
print(“With underscore separator: {:_d}”.format(big_number))
print(“Float with comma separator: {:,f}”.format(big_number))
百分数格式化
percentage = 0.85
print(“Percentage: {:.0%}”.format(percentage)) # 乘以100,保留0位小数,加%
print(“Percentage: {:.2%}”.format(percentage)) # 乘以100,保留2位小数,加%
自定义对象格式化 (format 方法)
class Coordinate:
def init(self, x, y):
self.x = x
self.y = y
# 实现 __format__ 方法来自定义格式化行为
def __format__(self, format_spec):
if format_spec == 'polar':
import math
r = math.sqrt(self.x**2 + self.y**2)
theta = math.atan2(self.y, self.x)
return f"Polar({r:.2f}, {math.degrees(theta):.2f} deg)" # 在 __format__ 内部可以使用 f-string 或其他格式化
# 如果没有匹配的 format_spec,可以使用默认或抛出错误
elif format_spec == '':
return f"Coord(x={self.x}, y={self.y})"
else:
# 可以处理更复杂的格式规范,或者抛出 TypeError
# For simplicity, let's just fall back to default repr or str
return repr(self)
point = Coordinate(3, 4)
print(“Default format: {}”.format(point))
print(“Polar format: {:polar}”.format(point))
“`
str.format()
方法的优缺点:
- 优点:
- 可读性大大提高: 格式字符串与要格式化的值分离,占位符
{}
清晰明了。 - 灵活性高: 支持位置索引、名称引用,可以轻松重用或按任意顺序使用值。
- 强大的格式控制: 格式规范迷你语言提供了丰富的选项来控制对齐、宽度、精度、数字格式等。
- 支持自定义对象的格式化 (
__format__
方法)。 - 向后兼容性好(Python 2.6+)。
- 可读性大大提高: 格式字符串与要格式化的值分离,占位符
- 缺点:
- 与 f-strings 相比,语法稍显冗长(需要重复写
.format()
)。 - 不能直接在
{}
内部嵌入复杂的表达式(只能是变量名或索引)。
- 与 f-strings 相比,语法稍显冗长(需要重复写
str.format()
方法是 %-formatting 的一个巨大进步,在 Python 3.6 之前是官方推荐的格式化方式。即使在 f-strings 出现后,理解 .format()
也是重要的,因为很多现有代码仍在使用它,且其格式规范迷你语言与 f-strings 共享。
3. f-strings (格式化字符串字面量)
f-strings 在 Python 3.6 中引入,是目前最推荐和最现代的字符串格式化方法。它通过在字符串前加上前缀 f
或 F
来创建一个 f-string。在 f-string 中,可以直接在 {}
内部嵌入 Python 表达式。
基本语法:
python
f"格式字符串中包含{表达式}"
F"格式字符串中包含{表达式}" # F 前缀与 f 相同,但主要用于当字符串包含 {} 时避免混淆,但在实际使用中很少需要
在 {}
内部,你可以放置任何有效的 Python 表达式,包括变量、函数调用、算术运算、方法调用等。表达式的值会在运行时被计算,然后格式化并插入到字符串中。
占位符 {表达式}
内部同样可以包含格式说明,语法与 .format()
方法中的 format_spec
完全相同:
{表达式!conversion:format_spec}
表达式
: 必需。 任何有效的 Python 表达式。!conversion
: 可选。与.format()
相同 (!s
,!r
,!a
)。:format_spec
: 可选。与.format()
方法的格式规范迷你语言完全相同。
示例:
“`python
基本用法
name = “Frank”
age = 40
print(f”Hello, {name}! You are {age} years old.”)
嵌入表达式
x = 10
y = 5
print(f”Sum: {x + y}, Product: {x * y}”)
调用函数或方法
text = “Python”
print(f”Length of ‘{text}’: {len(text)}”)
print(f”Uppercase: {text.upper()}”)
访问对象属性或字典元素
class Product:
def init(self, name, price):
self.name = name
self.price = price
p = Product(“Laptop”, 1200)
config = {‘cpu’: ‘i7’, ‘ram’: 16}
print(f”Product name: {p.name}, Price: ${p.price:.2f}”) # 结合格式化
print(f”Configuration: CPU={config[‘cpu’]}, RAM={config[‘ram’]}GB”)
使用格式规范 mini-language (与 .format() 相同)
pi = 3.1415926535
print(f”Pi formatted: {pi:.4f}”) # 精度
print(f”Percentage: {0.75:.1%}”) # 百分数
print(f”Large number: {1234567890:,d}”) # 千位分隔符
print(f”Binary of 10: {10:b}”) # 二进制
print(f”Aligned and zero-padded: {123:0>10d}”) # 对齐和零填充
使用 !r 进行 repr() 转换
my_list = [1, 2, 3]
print(f”List (str): {my_list!s}”) # 默认行为
print(f”List (repr): {my_list!r}”) # 显示 repr() 的结果
调试功能 (Python 3.8+)
在表达式后面加 =
会在结果中包含表达式文本和等号
debug_value = 42
debug_list = [10, 20, 30]
print(f”{debug_value=}”)
print(f”{debug_list=}”)
print(f”{len(debug_list)=}”)
可以与格式化结合使用调试功能
print(f”{pi=:.2f}”)
“`
f-strings 的优缺点:
- 优点:
- 极高的可读性: 格式字符串非常直观,直接在字符串中嵌入表达式,所见即所得。
- 简洁性: 语法简洁,不需要额外的
.format()
调用。 - 高性能: f-strings 是在解析时评估的,直接构建字符串,通常比
.format()
和 %-formatting 更快。 - 强大的功能: 可以嵌入任意表达式,极大地提高了灵活性。
- 支持与
.format()
相同的格式规范迷你语言,功能强大。 - 支持 Python 3.8+ 中的调试功能
=
.
- 缺点:
- 版本限制: 只在 Python 3.6 及以上版本可用。
- 不能在字符串中包含
{}
或\
字符时直接使用对应的字面量,需要使用双重花括号{{
或}}
,或者使用原始字符串r""
处理反斜杠。 - 由于直接评估表达式,如果在模板字符串中使用(例如来自用户输入),存在安全风险。这方面 Template Strings 更安全。
推荐: 在 Python 3.6+ 的环境中,f-strings 是首选的字符串格式化方法,因为它兼顾了可读性、简洁性和性能。
4. Template Strings (模板字符串)
string.Template
类提供了一种更简单、更安全的字符串替换方法,主要用于处理可能来自不可信来源的字符串模板,或者只需要进行简单的变量替换而不需要复杂的格式控制时。
Template strings 使用 $variable
或 ${variable}
作为占位符。
基本语法:
“`python
from string import Template
s = Template(“Hello, $name! Your score is $score.”)
print(s.substitute(name=”Grace”, score=99))
或者使用字典
data = {‘name’: ‘Henry’, ‘score’: 85}
print(s.substitute(data))
使用 ${} 处理紧跟占位符的字符
t = Template(“Look at this ${item}s.”)
print(t.substitute(item=”apple”)) # Output: Look at this apples.
safe_substitute 不会在缺少键时抛出 KeyError
s_safe = Template(“Greeting: $greeting, Subject: $subject”)
print(s_safe.safe_substitute(greeting=”Hi”)) # Output: Greeting: Hi, Subject: $subject
“`
Template Strings 的优缺点:
- 优点:
- 简单: 语法非常简单,易于理解和使用。
- 安全: 特别是
safe_substitute
方法,不会因为缺少键而抛出异常,也不会评估占位符中的任意表达式,因此处理用户提供的模板时相对安全。
- 缺点:
- 功能有限: 不支持复杂的格式控制(如对齐、精度、不同进制等)。只能进行简单的字符串替换。
- 语法不如 f-strings 或
.format()
直观。
适用场景: 主要用于需要简单变量替换,特别是模板字符串可能来自外部(如用户输入、配置文件)时,或者作为国际化 (i18n) 的一种简单方式。
格式规范迷你语言详解 (适用于 .format()
和 f-strings)
由于 .format()
和 f-strings 共享相同的格式规范迷你语言,我们将再次详细回顾其主要部分,并提供更多示例。
格式规范字符串位于占位符内部的冒号 :
后面。
[[fill]align][sign][#][0][width][grouping_option][.precision][type]
-
Fill 和 Align (
[fill]align
)fill
: 任何字符。默认为空格。align
:<
,>
,=
,^
。<
: 左对齐 (字符串默认)。>
: 右对齐 (数字默认)。=
: 零填充时将填充放在符号和数字之间 (仅数字)。^
: 居中对齐。
- 示例:
python
print(f"'{'hello':<10}'") # 'hello '
print(f"'{'world':>10}'") # ' world'
print(f"'{'python':^10}'") # ' python '
print(f"'{'center':-^10}'") # '--center--'
print(f"'{123:0=10d}'") # '0000000123' (0填充在符号/空格后)
print(f"'{{-123:0=10d}}'".format(-123)) # '-000000123' (适用于 .format())
-
Sign (
[sign]
)+
: 总是显示符号 (+/-)。-
: 只显示负号 (默认)。: 正数显示空格,负数显示负号。
- 示例:
python
print(f"Positive: {100:+d}, Negative: {-100:+d}") # Positive: +100, Negative: -100
print(f"Positive: {100: d}, Negative: {-100: d}") # Positive: 100, Negative: -100
-
Alternate form (
[#]
)- 用于不同类型的特殊前缀或行为。
- 整数 (
b
,o
,x
,X
): 添加进制前缀 (0b
,0o
,0x
,0X
). - 浮点数 (
f
,F
,e
,E
,g
,G
): 总是显示小数点,即使后面没有数字。对于g
,G
类型,保留末尾的零。 - 示例:
python
print(f"Binary: {10:#b}, Octal: {10:#o}, Hex: {255:#x}") # Binary: 0b1010, Octal: 0o12, Hex: 0xff
print(f"Float: {10.0:#.0f}") # Float: 10.
print(f"General: {10.0:#g}") # General: 10.0000
-
Zero padding (
[0]
)- 用
0
填充到指定的宽度。 - 示例:
python
print(f"Zero padded: {123:05d}") # Zero padded: 00123
# 注意:与对齐结合时,0通常放在符号后 (如果指定了 '=') 或默认右对齐。
print(f"Zero padded left align: {123:0<5d}") # 12300 (0 作为填充字符)
print(f"Zero padded right align: {123:0>5d}") # 00123 (0 作为填充字符)
- 用
-
Width (
[width]
)- 指定字段的最小总宽度。
- 示例:
python
print(f"Width 10: {'short':10}") # Width 10: short
print(f"Width 3: {'longer':3}") # Width 3: longer (宽度不足时不会截断,除非使用 .precision 对字符串)
-
Grouping option (
[grouping_option]
),
:使用逗号作为千位分隔符 (基于 locale 的千位分隔符,但默认是逗号)。_
: 使用下划线作为千位分隔符 (PEP 515)。- 示例:
python
print(f"Comma separated: {1000000:,d}") # Comma separated: 1,000,000
print(f"Underscore separated: {1000000:_d}") # Underscore separated: 1_000_000
print(f"Float comma separated: {12345.67:,.2f}") # Float comma separated: 12,345.67
-
Precision (
[.precision]
)- 跟在小数点
.
后面。 - 浮点数 (
f
,e
,E
,%
): 小数点后的位数。 - 浮点数 (
g
,G
): 总有效数字位数。 - 字符串 (
s
): 最大字符数 (截断字符串)。 - 示例:
python
print(f"Float precision 3: {3.14159:.3f}") # Float precision 3: 3.142 (四舍五入)
print(f"General precision 4: {123.456789:.4g}") # General precision 4: 123.5
print(f"String precision 5: {'HelloWorld':.5s}") # String precision 5: Hello
- 跟在小数点
-
Type (
[type]
)- 指定如何将值转换为字符串。前面已经详细列出。
- 示例:
python
print(f"Decimal: {100:d}, Hex: {100:x}")
print(f"Float: {123.45:f}, Scientific: {123.45:e}")
print(f"Character: {97:c}") # 'a'
组合使用格式规范:
可以组合多个格式选项(按照上面列出的顺序)。
“`python
value = -12345.6789
宽度、对齐、填充、符号、分组、精度、类型
print(f”Formatted: ‘{value:=^20,.2f}'”) # Formatted: ‘— -12,345.68—‘
– : 填充字符
= : 填充在符号和数字之间,居中对齐
^ : 居中对齐 (这里 ‘=’ 优先于 ‘^’ 对数字起作用,但填充会应用到整个字段) – 更准确地说,’=’ 强制填充在符号后,然后 ‘<>^’ 决定整体对齐
20: 总宽度 20
, : 千位分隔符
.2: 精度 2
f : 浮点数类型
“`
选择合适的格式化方法
在现代 Python (3.6+) 中:
- f-strings 是绝大多数情况下的首选。它们简洁、易读、快速,并支持强大的格式化选项。如果需要嵌入变量和表达式,或者进行复杂的格式控制,f-strings 是最佳选择。
.format()
方法 仍然有效且功能强大。如果需要支持 Python 3.5 或更早的版本,或者在某些特定场景下觉得其将格式字符串与值分离的风格更清晰(尽管这种情况不多),可以使用它。其格式规范迷你语言与 f-strings 共享,学习成本不高。- %-formatting 不推荐用于新代码。了解它是为了阅读和维护遗留代码。
- Template Strings 适用于特定的简单替换场景,尤其是处理来自不可信来源的模板时,因为它不执行表达式。
通常,你可以遵循以下简单规则:
- Python 3.6+: 使用 f-strings。
- Python < 3.6: 使用
.format()
方法。 - 处理不信任的简单模板: 使用
string.Template
.
总结
字符串格式化是 Python 编程中一项基础且重要的技能。从早期的 %-formatting 到现代的 f-strings,Python 提供了越来越强大、灵活和易读的工具来构建动态字符串。
%-formatting 语法古老,不推荐新用;str.format()
方法是现代格式化的基石,提供了强大的格式规范迷你语言;而 f-strings 则在此基础上实现了更高的简洁性、可读性和性能,是当前最主流和推荐的方法。Template Strings 则在简单和安全替换场景下有其独特的价值。
掌握 f-strings 及其背后的格式规范迷你语言,将极大地提升你在 Python 中处理文本输出的效率和代码的可读性。通过本文的详细讲解和示例,希望能帮助你全面理解并熟练运用 Python 的字符串格式化技术,写出更清晰、更高效的代码。