Python 字符串格式化详解 – wiki基地


Python 字符串格式化详解:从古老到现代的演进与精通

字符串是 Python 中最常用的数据类型之一,而将变量、表达式或其他值嵌入到字符串中,构建出具有特定结构的文本,则是编程中的常见任务。这个过程被称为“字符串格式化”。Python 提供了多种强大的字符串格式化方法,随着语言的发展,这些方法也在不断演进,提供了更加灵活、易读和高效的选项。

本文将深入探讨 Python 中各种字符串格式化技术,从早期的方法到现代的最佳实践,详细讲解它们的用法、特性以及底层的格式化规范迷你语言,帮助你全面掌握 Python 的字符串格式化艺术。

为什么需要字符串格式化?

想象一下,你需要输出一段包含动态信息(如用户名、分数、日期)的文本。最原始的方法可能是简单地使用字符串连接:

python
name = "Alice"
score = 95
message = "Hello, " + name + "! Your score is " + str(score) + "."
print(message)

这种方法在处理少量、类型一致的数据时尚可接受,但很快就会暴露出问题:

  1. 可读性差: 当需要连接的变量很多时,代码会变得冗长且难以阅读,字符串和变量交织在一起,难以分辨。
  2. 类型限制: 只能连接字符串类型。如果连接的不是字符串,需要手动进行类型转换(如 str(score)),增加了代码的复杂性和出错的可能性。
  3. 格式控制困难: 难以控制数值的显示格式(如小数点位数、千位分隔符、对齐方式),需要额外的字符串操作函数。

字符串格式化技术应运而生,旨在解决这些问题,提供一种更清晰、更灵活、更强大的方式来构建动态字符串。

演进之路:Python 字符串格式化方法

Python 历史上主要经历了以下几种字符串格式化方法:

  1. %-formatting (百分号格式化): 借鉴了 C 语言的 printf 风格,是 Python 早期版本主要使用的格式化方法。
  2. str.format() 方法: 在 Python 2.6 引入,是比 %-formatting 更灵活、更强大的替代方案,推荐在 Python 2.x 和 3.x 中使用(在 f-strings 出现之前)。
  3. f-strings (格式化字符串字面量): 在 Python 3.6 引入,是目前最推荐和最受欢迎的格式化方法,提供了极高的可读性和性能。
  4. 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 会在十六进制数前加上 0x0X。对于浮点数,总是包含小数点,即使后面没有数字。对于 gG 类型,保留末尾的零。
  • width: 可选。指定格式化后字段的最小宽度。如果值不足指定宽度,会根据对齐方式进行填充。
  • .precision: 可选。
    • 对于浮点数 (f, e, E, g, G, %):指定小数点后显示的位数(对于 gG,指定总有效数字位数)。
    • 对于字符串 (s):指定输出的最大字符数。
  • type: 必需。 指定要格式化的值的类型以及如何表示它。常见的 type 包括:
    • s: 字符串 (使用 str() 进行转换)。
    • r: 字符串 (使用 repr() 进行转换)。
    • c: 单个字符 (接受一个整数或单个字符的字符串)。
    • d: 带符号的十进制整数。
    • i: 带符号的十进制整数 (与 d 相同)。
    • o: 无符号八进制整数。
    • x: 无符号十六进制整数 (小写)。
    • X: 无符号十六进制整数 (大写)。
    • e: 浮点数 (科学计数法,小写 e)。
    • E: 浮点数 (科学计数法,大写 E)。
    • f: 浮点数 (定点表示法)。
    • F: 浮点数 (定点表示法,与 f 相同,但在特殊值(如 NaN, Inf)上可能不同)。
    • g: 浮点数 (通用格式)。根据数值大小,自动选择 ef 格式中更简洁的一种。精度指定的是总有效数字位数。
    • G: 浮点数 (通用格式),使用 EF
    • %: 字面量的 ‘%’ 字符 (不需要对应的值)。

示例:

“`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())。
    • 不能直接在 {} 内部嵌入复杂的表达式(只能是变量名或索引)。

str.format() 方法是 %-formatting 的一个巨大进步,在 Python 3.6 之前是官方推荐的格式化方式。即使在 f-strings 出现后,理解 .format() 也是重要的,因为很多现有代码仍在使用它,且其格式规范迷你语言与 f-strings 共享。

3. f-strings (格式化字符串字面量)

f-strings 在 Python 3.6 中引入,是目前最推荐和最现代的字符串格式化方法。它通过在字符串前加上前缀 fF 来创建一个 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]

  1. 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())
  2. 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
  3. 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
  4. 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 作为填充字符)
  5. Width ([width])

    • 指定字段的最小总宽度。
    • 示例:
      python
      print(f"Width 10: {'short':10}") # Width 10: short
      print(f"Width 3: {'longer':3}") # Width 3: longer (宽度不足时不会截断,除非使用 .precision 对字符串)
  6. 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
  7. 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
  8. 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 适用于特定的简单替换场景,尤其是处理来自不可信来源的模板时,因为它不执行表达式。

通常,你可以遵循以下简单规则:

  1. Python 3.6+: 使用 f-strings。
  2. Python < 3.6: 使用 .format() 方法。
  3. 处理不信任的简单模板: 使用 string.Template.

总结

字符串格式化是 Python 编程中一项基础且重要的技能。从早期的 %-formatting 到现代的 f-strings,Python 提供了越来越强大、灵活和易读的工具来构建动态字符串。

%-formatting 语法古老,不推荐新用;str.format() 方法是现代格式化的基石,提供了强大的格式规范迷你语言;而 f-strings 则在此基础上实现了更高的简洁性、可读性和性能,是当前最主流和推荐的方法。Template Strings 则在简单和安全替换场景下有其独特的价值。

掌握 f-strings 及其背后的格式规范迷你语言,将极大地提升你在 Python 中处理文本输出的效率和代码的可读性。通过本文的详细讲解和示例,希望能帮助你全面理解并熟练运用 Python 的字符串格式化技术,写出更清晰、更高效的代码。


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部