String formatting: % vs. .format vs. f-string literal

String formatting: % vs. .format vs. f-string literal

技术背景

在Python编程中,字符串格式化是一项常见需求,有多种方式可以实现,包括%操作符、.format()方法和f-string(自Python 3.6引入)。不同的格式化方式有各自的特点和适用场景,了解它们之间的区别有助于编写更高效、更易读的代码。

实现步骤

%操作符

%操作符是Python中较早的字符串格式化方式,类似于C语言中的printf。它可以接受一个变量或一个元组作为参数。示例如下:

1
2
name = "John"
print("Hello %s" % name)

但如果name是一个元组,需要特殊处理:

1
2
name = (1, 2, 3)
print("Hello %s" % (name,))

.format()方法

.format()方法是Python 2.6及以后版本引入的新格式化方式,解决了%操作符的一些问题,语法更灵活、更清晰。示例如下:

1
2
name = "John"
print("Hello {}".format(name))

还可以通过索引指定参数位置:

1
2
tu = (12, 45, 22222, 103, 6)
print('{0} {2} {1} {2} {3} {2} {4} {2}'.format(*tu))

也可以使用对象属性:

1
2
3
4
5
6
7
class A(object):
def __init__(self, x, y):
self.x = x
self.y = y

a = A(2, 3)
print('x is {0.x}, y is {0.y}'.format(a))

f-string

f-string是Python 3.6引入的新特性,通过在字符串前加f前缀,在字符串中使用{}来引用变量,语法简洁,性能较好。示例如下:

1
2
3
origin = "London"
destination = "Paris"
print(f"from {origin} to {destination}")

核心代码

性能测试代码

1
2
3
4
5
import timeit

print('format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')"))
print('%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')"))
print('f-string:', timeit.timeit("f'{1}{1.23}{\"hello\"}'"))

日志记录示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import logging

class NewStyleLogMessage(object):
def __init__(self, message, *args, **kwargs):
self.message = message
self.args = args
self.kwargs = kwargs

def __str__(self):
args = (i() if callable(i) else i for i in self.args)
kwargs = dict((k, v() if callable(v) else v) for k, v in self.kwargs.items())
return self.message.format(*args, **kwargs)

N = NewStyleLogMessage
logging.debug(N('Lazily formatted log entry: {0} {keyword}', 123, keyword='foo'))

最佳实践

  • 如果需要与Python 2.5兼容,建议使用%操作符。
  • 如果代码需要在Python 2.6及以上版本运行,且追求代码的可读性和灵活性,推荐使用.format()方法。
  • 如果使用Python 3.6及以上版本,f-string是首选,它简洁高效。

常见问题

%操作符的元组问题

当参数是元组时,需要将其包装成单元素元组,否则可能抛出TypeError

.format()方法的编码问题

在Python 2中,'{}'.format(unicode_string)可能会尝试对unicode_string进行编码,导致UnicodeEncodeError

f-string的版本兼容性问题

f-string只能在Python 3.6及以上版本使用,在早期版本中会抛出SyntaxError

格式化正则表达式问题

在格式化正则表达式时,.format()方法可能会引发IndexError,此时可以使用%操作符。例如:

1
print('%(type_names)s [a-z]{2}' % {'type_names': 'triangle|square'})

嵌套花括号问题

.format()方法不支持嵌套花括号的格式化,而%操作符可以正常处理。例如:

1
print('{%s, %s}' % (1, 2))

String formatting: % vs. .format vs. f-string literal
https://119291.xyz/posts/string-formatting-comparison/
作者
ww
发布于
2025年6月30日
许可协议