当前位置: 首页 > news >正文

Python基础:字符串格式化之百分号%方式

Python基础:字符串格式化之百分号%方式

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

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

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

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

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

2.1 语法形式

# 基本语法result="格式化字符串"%(1,2,...)# 最简单的例子name='小明'age=25text='我叫%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.5items=[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=25height=1.75print('%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.141592653589793print('%.2f'%pi)# 3.14(保留2位小数)print('%.4f'%pi)# 3.1416(保留4位小数,四舍五入)print('%.10f'%pi)# 3.1415926536print('%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)forname,age,scoreinstudents: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)# helloprint('%r'%x)# 'hello'(带引号)# 对于字符串,区别很明显name='小明'print('名字是%s'%name)# 名字是小明print('名字是%r'%name)# 名字是'小明'# 对于数字,区别不大print('%s'%42)# 42print('%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=10precision=3print('%*.*f'%(width,precision,3.14159))# ' 3.142'(宽度10,保留3位小数)# 这在生成动态格式的报告中很有用defprint_table(data,col_widths):forrowindata:format_str=''forwidthincol_widths:format_str+='%-*s '# 构建: '%-*s %-*s %-*s 'print(format_str%tuple(itemforpairinzip(col_widths,row)foriteminpair))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',))# helloprint('%s'%(('a','b'),))# ('a', 'b') —— 整个元组被当作一个值

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

# %d 不接受浮点数# print('分数:%d' % 95.5) # TypeError# 解决方法:先转换print('分数:%d'%int(95.5))# 分数:95# 或者直接用%sprint('分数:%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=25score=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推荐使用百分号importlogging 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=}' 更好,但老习惯改不掉

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

defgenerate_sales_report(month,data):"""生成销售报告"""report=[]report.append('='*50)report.append('%s月销售报告'%month)report.append('='*50)report.append('')report.append('%-20s %-10s %-10s'%('商品名称','销量','销售额'))total_quantity=0total_revenue=0.0foritem_name,quantity,priceindata: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()——功能更强大的格式化方式。

http://www.jsqmd.com/news/961308/

相关文章:

  • Sunshine游戏串流完整指南:如何快速搭建免费高效的自托管游戏服务器
  • 2026年PDF压缩完全指南:免费方法+电脑自带软件详细教程
  • 2026注册公司服务商推荐:深圳本土代办深度测评,我的财务管理入选 - 速递信息
  • [特殊字符] 论文查重居然能免费?书匠策AI这个隐藏功能,90%的同学还不知道!
  • 别再只用FFT了!用MATLAB玩转Chirp Z变换(CZT),轻松实现频谱局部放大
  • Cursor点击当前文件:跳转目录树
  • Veo 2光影响应延迟超23ms?这是设计缺陷还是安全锁?深度溯源光控指令队列缓冲区溢出漏洞(CVE-2024-Veo-Light-01已确认)
  • 买柜子必看:到底什么是三段力铰链?听内行人给你说句大实话! - 资讯焦点
  • 以“车路运能”聚势,千方科技自动驾驶干线物流业务稳步推进
  • 如何快速掌握DeepL翻译插件:浏览器内专业级翻译体验完全指南
  • 2026择校指南:四川本地就业率高的大学院校盘点 - 品牌2026
  • 本地部署 Hermes Agent,私人智能体在自己电脑常驻运行
  • Beyond Compare 5激活终极指南:免费解锁专业文件对比工具完整教程
  • 用Arduino和FFT搞定电子设计大赛最难故障:C1电容加倍2°相移检测实战
  • 终极Dell G15散热控制方案:开源高效的硬件级温度管理工具
  • 别再让JBoss裸奔了!手把手教你复现并修复那个经典的未授权访问漏洞
  • 3种方法彻底解决音乐资源碎片化:MusicFree插件系统的革命性聚合方案
  • MuleSoft+LLM企业级AI编排实战:构建可控、合规、可审计的智能工作流
  • 基于STC89C52和MF RC522的13.56MHz RFID门禁系统实战资料包
  • 昆明装修哪家靠谱?5 家本地主流装企客观盘点 + 装修避坑参考
  • Hitboxer深度解析:亚毫秒级SOCD键盘映射工具的技术架构与实现
  • 老路由焕新颜:给小米路由器R2D刷上Misstar Tools,实现广告过滤+内网穿透+离线下载
  • 杨杨二手家具家电:龙泉驿区空调回收上门 - LYL仔仔
  • 千方科技携手重庆数字交通 拓城际自动驾驶货运示范应用
  • 哇塞出评-PDD自动出评-批量上货-智能匹配订单
  • OpenRPA:重新定义企业级开源RPA,如何打破传统自动化成本壁垒
  • 别再乱用马尔可夫链了!先花5分钟用SPSS/Excel做个马氏性检验避坑
  • ABAQUS里一键生成不重叠二维圆颗粒模型的Python工具
  • 2026高考择校攻略:四川本地就业率高的大学院校有哪些? - 品牌2026
  • 遗传算法实战:N皇后问题的可复现求解与调参指南