Python基础指南之字符串格式化百分号%的用法详解

 更新时间:2026年06月09日 09:23:10   作者:星河耀银海  
本文详细介绍了Python最古老的格式化方式——百分号%的用法,包括基本语法、占位符、精度控制及实战示例;并对比了其与str.format()和f-string的差异,强调了百分号格式化在老项目维护及简单调试中的应用价值

一、开篇:最古老的Python格式化方式

Python有三种字符串格式化方式,按出现的时间顺序:

  • 百分号 %:Python诞生时就有的,最古老
  • str.format():Python 2.6引入,功能更强大
  • f-string(f'...'):Python 3.6引入,最现代、最推荐

今天我们先讲第一种——百分号格式化。虽然它是"老古董",但很多老项目中仍然大量使用,而且某些场景下它写起来特别简洁。了解它能帮你读懂和维护存量代码,也能在一些简单场景中快速完成任务。

二、百分号格式化的基本语法

2.1 语法形式

# 基本语法
result = "格式化字符串" % (值1, 值2, ...)

# 最简单的例子
name = '小明'
age = 25
text = '我叫%s,今年%d岁' % (name, age)
print(text)  # 我叫小明,今年25岁

语法结构:

  • %s%d 这些是占位符,标记了"这里要插入一个值"
  • 字符串末尾的 %运算符,连接模板和实际值
  • (name, age)值的元组,按顺序填入占位符

2.2 占位符速查表

占位符含义示例
%s字符串(自动调用str())'%s' % 'hello''hello'
%d十进制整数'%d' % 42'42'
%i整数(同%d)'%i' % 42'42'
%f浮点数'%f' % 3.14'3.140000'
%e科学计数法(小写e)'%e' % 1000'1.000000e+03'
%E科学计数法(大写E)'%E' % 1000'1.000000E+03'
%x十六进制(小写)'%x' % 255'ff'
%X十六进制(大写)'%X' % 255'FF'
%o八进制'%o' % 8'10'
%c字符(接受整数或单个字符)'%c' % 65'A'
%r字符串repr()表示'%r' % 'hello'"'hello'"
%%百分号本身'%%''%'

2.3 基本使用示例

# %s——万能占位符(适合快速输出)
name = '小明'
score = 95.5
items = [1, 2, 3]

print('姓名:%s' % name)          # 姓名:小明
print('分数:%s' % score)         # 分数:95.5(自动转字符串)
print('列表:%s' % items)         # 列表:[1, 2, 3]

# %d——整数(不接受浮点数)
print('年龄:%d' % 25)           # 年龄:25
# print('年龄:%d' % 25.5)       # TypeError!%d不能接受浮点数

# %f——浮点数
print('π ≈ %f' % 3.14159)        # π ≈ 3.141590(默认6位小数)

# 多个占位符
name = '小明'
age = 25
height = 1.75
print('%s,%d岁,身高%.2f米' % (name, age, height))
# 小明,25岁,身高1.75米

注意:当只有一个值时,括号可以省略;但如果是元组,需要括号:

print('%s' % 'hello')       # 单个值,可以不写括号
# print('%s' % ('hello',))  # 也可以写括号
# print('%s %s' % 'a', 'b') # 错误!多个值不用括号会报错
print('%s %s' % ('a', 'b')) # 正确

三、格式化精度控制

3.1 控制浮点数的小数位数

pi = 3.141592653589793

print('%.2f' % pi)    # 3.14(保留2位小数)
print('%.4f' % pi)    # 3.1416(保留4位小数,四舍五入)
print('%.10f' % pi)   # 3.1415926536
print('%f' % pi)      # 3.141593(默认6位)

# 整数也可以用小数控制(但通常不需要)
print('%.2f' % 42)    # 42.00

3.2 控制宽度和对齐

# 固定宽度(右对齐,默认)
print('%10s' % 'hello')      # '     hello'
print('%10d' % 42)           # '        42'
print('%10.2f' % 3.14)       # '      3.14'

# 左对齐(负号)
print('%-10s' % 'hello')     # 'hello     '
print('%-10d' % 42)          # '42        '

# 补零(数字前面补0)
print('%010d' % 42)          # '0000000042'
print('%010.2f' % 3.14)      # '0000003.14'

# 居中对齐?百分号不支持,需要format()或f-string

3.3 格式化实战

# 打印对齐的表格
students = [
    ('小明', 20, 85.5),
    ('小红', 21, 92.0),
    ('小刚', 19, 78.5),
]

print('%-8s %-6s %-8s' % ('姓名', '年龄', '成绩'))
print('-' * 24)
for name, age, score in students:
    print('%-8s %-6d %-8.1f' % (name, age, score))

# 输出:
# 姓名       年龄     成绩
# ------------------------
# 小明       20     85.5
# 小红       21     92.0
# 小刚       19     78.5

四、%s 和 %r 的区别

# %s:调用str()——给人看的
# %r:调用repr()——给调试看的

x = 'hello'
print('%s' % x)  # hello
print('%r' % x)  # 'hello'(带引号)

# 对于字符串,区别很明显
name = '小明'
print('名字是%s' % name)   # 名字是小明
print('名字是%r' % name)   # 名字是'小明'

# 对于数字,区别不大
print('%s' % 42)   # 42
print('%r' % 42)   # 42

# repr在调试中很有用
value = '  hello  \n'
print('str: [%s]' % value)    # str: [  hello  ]
print('repr: [%r]' % value)   # repr: ['  hello  \n'](看到换行符和空格)

%s 适合最终输出(给用户看),%r 适合调试日志(给开发者看)。

五、百分号格式化的高级用法

5.1 用字典传值

# 当格式化字符串很长、需要插入的值很多时,用字典可以避免一一对应的混乱

person = {
    'name': '小明',
    'age': 25,
    'city': '北京',
    'job': '软件工程师'
}

template = '我叫%(name)s,今年%(age)d岁,来自%(city)s,职业是%(job)s。'
print(template % person)
# 我叫小明,今年25岁,来自北京,职业是软件工程师。

# 用字典的优势:可以重复使用同一个值
template = '%(name)s的年龄是%(age)d,%(name)s住在%(city)s。'
print(template % person)
# 小明的年龄是25,小明住在北京。

5.2 动态宽度(用*传宽度)

# 宽度可以动态指定
width = 10
precision = 3

print('%*.*f' % (width, precision, 3.14159))
# '     3.142'(宽度10,保留3位小数)

# 这在生成动态格式的报告中很有用
def print_table(data, col_widths):
    for row in data:
        format_str = ''
        for width in col_widths:
            format_str += '%-*s  '
        # 构建: '%-*s  %-*s  %-*s  '
        print(format_str % tuple(
            item for pair in zip(col_widths, row) for item in pair
        ))

data = [('小明', '北京', '工程师'), ('小红', '上海', '设计师')]
print_table(data, [8, 6, 8])

六、常见错误和注意事项

6.1 占位符和值的数量不匹配

# ❌ 占位符比值多
# print('%s %s %s' % ('a', 'b'))  # TypeError: not enough arguments

# ❌ 值比占位符多
# print('%s' % ('a', 'b'))  # TypeError: not all arguments converted

# ✅ 占位符和值数量对应
print('%s %s' % ('a', 'b'))  # a b

# 只有一个值时不需要元组(但如果值本身是元组要注意)
print('%s' % ('hello',))     # hello
print('%s' % (('a', 'b'),))  # ('a', 'b') —— 整个元组被当作一个值

6.2 占位符和值的类型不匹配

# %d 不接受浮点数
# print('分数:%d' % 95.5)  # TypeError

# 解决方法:先转换
print('分数:%d' % int(95.5))   # 分数:95

# 或者直接用%s
print('分数:%s' % 95.5)        # 分数:95.5

# %f 不接受字符串
# print('价格:%f' % '十元')  # TypeError

6.3 忘记转义百分号

# 如果你想在格式化字符串中显示百分号本身
# ❌ 错误写法
# print('完成度:%d%' % 80)  # ValueError

# ✅ 用 %% 转义
print('完成度:%d%%' % 80)  # 完成度:80%

# 多个百分号
print('增长率为%.2f%%' % 15.678)  # 增长率为15.68%

七、百分号格式化 vs format() vs f-string

name = '小明'
age = 25
score = 95.5

# 三种方式对比
# 1. 百分号——古老简洁
s1 = '我叫%s,今年%d岁,成绩%.1f分' % (name, age, score)

# 2. format()——功能强大
s2 = '我叫{},今年{}岁,成绩{:.1f}分'.format(name, age, score)

# 3. f-string——最现代最推荐
s3 = f'我叫{name},今年{age}岁,成绩{score:.1f}分'

print(s1)  # 三种方式输出一样
print(s2)
print(s3)
特性% 格式化str.format()f-string
Python版本所有版本2.6+3.6+
可读性一般较好最好
表达式支持不支持支持支持
字典引用支持支持支持
性能一般一般最快
重复使用模板支持支持需重新构建

选择建议:

  • 新代码:优先使用 f-string
  • 需要复用模板:使用 str.format()
  • 维护老代码:了解百分号语法,不要强行改
  • 简单快速调试:百分号一行搞定 '%s=%r' % (name, value)

八、何时仍然使用百分号

# 场景一:日志模块——logging推荐使用百分号
import logging
logging.basicConfig(level=logging.INFO)

# logging内部使用百分号格式化
# 这样写可以让日志系统延迟执行字符串格式化(性能优化)
name = '小明'
logging.info('用户 %s 登录了系统', name)
# 注意:这里是逗号分隔,不是%运算符

# 场景二:维护使用百分号的老代码
# 如果整个项目已经用了百分号风格,保持一致
# 不要在新旧风格间跳来跳去

# 场景三:简单的调试输出
print('x=%d, y=%d, sum=%d' % (x, y, x + y))
# 虽然 f'{x=} {y=}' 更好,但老习惯改不掉

九、实战:用百分号格式化生成报告

def generate_sales_report(month, data):
    """生成销售报告"""
    report = []
    report.append('=' * 50)
    report.append('%s月销售报告' % month)
    report.append('=' * 50)
    report.append('')
    report.append('%-20s %-10s %-10s' % ('商品名称', '销量', '销售额'))

    total_quantity = 0
    total_revenue = 0.0

    for item_name, quantity, price in data:
        revenue = quantity * price
        report.append('%-20s %-10d ¥%-9.2f' % (item_name, quantity, revenue))
        total_quantity += quantity
        total_revenue += revenue

    report.append('-' * 50)
    report.append('%-20s %-10d ¥%-9.2f' % ('合计', total_quantity, total_revenue))
    report.append('=' * 50)

    return '\n'.join(report)


data = [
    ('Python编程书', 150, 59.9),
    ('机械键盘', 80, 299.0),
    ('显示器支架', 45, 159.0),
    ('USB数据线', 300, 19.9),
]

print(generate_sales_report('5', data))

十、本篇小结

百分号格式化是Python最古老的字符串格式化方式:

  1. 基本语法"模板%s %d" % (值1, 值2)
  2. 常用占位符%s(字符串)、%d(整数)、%f(浮点数)
  3. 精度控制%.2f(保留2位小数)、%10s(宽度10右对齐)、%-10s(左对齐)
  4. 字典传值%(name)s 按名称引用,适合长模板
  5. 转义百分号:用 %% 输出一个 %

虽然在新项目中推荐使用 f-string,但百分号格式化在日志模块、老项目维护、简单调试中仍然有其位置。下一篇我们进入 str.format()——功能更强大的格式化方式。

以上就是Python基础指南之字符串格式化百分号%的用法详解的详细内容,更多关于Python字符串格式化的资料请关注脚本之家其它相关文章!

相关文章

  • Python渗透测试入门之Scapy库的使用详解

    Python渗透测试入门之Scapy库的使用详解

    Scapy 是一个用来解析底层网络数据包的Python模块和交互式程序,该程序对底层包处理进行了抽象打包,使得对网络数据包的处理非常简便。本文就来聊聊它的具体使用,希望对大家有所帮助
    2023-03-03
  • 通过Python实现一个简单的html页面

    通过Python实现一个简单的html页面

    这篇文章主要介绍了通过Python写一个简单的html页面,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • python实现扫雷小游戏

    python实现扫雷小游戏

    这篇文章主要为大家详细介绍了python实现扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • django 单表操作实例详解

    django 单表操作实例详解

    这篇文章主要介绍了django 单表操作实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • python使用turtle库与random库绘制雪花

    python使用turtle库与random库绘制雪花

    这篇文章主要为大家详细介绍了python使用turtle库与random库绘制雪花,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • 详解使用Selenium爬取豆瓣电影前100的爱情片相关信息

    详解使用Selenium爬取豆瓣电影前100的爱情片相关信息

    这篇文章主要介绍了详解使用Selenium爬取豆瓣电影前100的爱情片相关信息,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Django与遗留的数据库整合的方法指南

    Django与遗留的数据库整合的方法指南

    这篇文章主要介绍了Django与遗留的数据库整合的方法指南,Django是最具人气的Python开发框架,需要的朋友可以参考下
    2015-07-07
  • Python实现查找匹配项作处理后再替换回去的方法

    Python实现查找匹配项作处理后再替换回去的方法

    这篇文章主要介绍了Python实现查找匹配项作处理后再替换回去的方法,涉及Python字符串查找、转换、输出等相关操作技巧,需要的朋友可以参考下
    2017-06-06
  • matplotlib实现显示伪彩色图像及色度条

    matplotlib实现显示伪彩色图像及色度条

    今天小编就为大家分享一篇matplotlib实现显示伪彩色图像及色度条,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • Django自定义全局403、404、500错误页面的示例代码

    Django自定义全局403、404、500错误页面的示例代码

    这篇文章主要介绍了Django自定义全局403、404、500错误页面的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03

最新评论