Python 格式化字符串全面对比对比 Python 中五种主要的字符串格式化方式% 运算符、str.format()、f-strings (3.6)、Template 模板字符串以及它们各自的适用场景、性能差异和安全注意事项。import stringimport timefrom datetime import datetime# # 第一部分四种格式化方式详解# # -------------------------------------------------------------------# 1. % 格式化经典风格# -------------------------------------------------------------------def 百分号格式化():% 格式化源于 C 语言的 printf 风格name 张三age 28score 92.5result1 姓名: %s, 年龄: %d % (name, age)print(f1: {result1})result2 分数: %.1f (百分位: %.0f%%) % (score, score)print(f2: {result2})result3 |%10s|%-10s| % (右对齐, 左对齐)print(f3: {result3})result4 用户: %(name)s, 邮箱: %(email)s % {name: 张三, email: zhangsanexample.com}print(f4: {result4})print(\n格式说明符: %s %d %f %x %o %e)百分号格式化()# -------------------------------------------------------------------# 2. str.format() 方法# -------------------------------------------------------------------def format方法():name 张三age 28score 92.5result1 姓名: {}, 年龄: {}, 分数: {}.format(name, age, score)print(f1: {result1})result2 {0} 说: {0} 今年 {1} 岁.format(name, age)print(f2: {result2})result3 用户: {name}, 年龄: {age}.format(namename, ageage)print(f3: {result3})result4 分数: {:.2f} (百分制: {:.0%}).format(score, score / 100)print(f4: {result4})result5 |{:10}|{:^10}|{:10}|.format(左对齐, 居中, 右对齐)print(f5: {result5})big_num 1234567890result6 {:,}.format(big_num)print(f6: {result6})class User:def __init__(self, n, a):self.name nself.age au User(李四, 35)result7 用户信息: {0.name}, 年龄: {0.age}.format(u)print(f7: {result7})val 255print(f\n进制格式: {val} {val:b}b {val:o}o {val:x}h)format方法()# -------------------------------------------------------------------# 3. f-strings (3.6)# -------------------------------------------------------------------def f字符串():name 张三age 28score 92.5result1 f姓名: {name}, 年龄: {age}print(f1: {result1})result2 f明年 {age 1} 岁, 分数提升 {score * 1.1:.1f}print(f2: {result2})result3 f名字大写: {name.upper()}, 名字长度: {len(name)}print(f3: {result3})x 42y 3.14print(f4: {x}, {y}, {x y}) # 说明符 (3.8)print(f5: |{name:10}|{name:^10}|{name:10}|)now datetime.now()print(f6: 当前时间: {now:%Y-%m-%d %H:%M:%S})data {name: 张三, age: 28}print(f7: {data[name]} 今年 {data[age]} 岁)big 1234567890print(f8: 千位分隔: {big:,})print(f9: 百分比: {0.1234:.2%})print(f10: 科学计数: {big:.2e})f字符串()# -------------------------------------------------------------------# 4. Template 模板字符串# -------------------------------------------------------------------def 模板字符串():t string.Template(你好, $name! 你的分数是 $score 分。)result t.substitute(name张三, score92.5)print(f1: {result})t2 string.Template($name 今年 $age 岁)result2 t2.safe_substitute(name李四)print(f2: {result2})data {name: 王五, age: 30, city: 北京}t3 string.Template($name 来自 $city, 今年 $age 岁)result3 t3.substitute(data)print(f3: {result3})恶意输入 ${__import__(os).system(rm -rf /)}t4 string.Template(用户输入: $input)result4 t4.safe_substitute(input恶意输入)print(f4 (安全): {result4})print(\nTemplate 适用场景: 用户自定义模板、配置文件模板)模板字符串()# # 第二部分高级技巧与对比# # -------------------------------------------------------------------# 5. !s / !r / !a 转换标志# -------------------------------------------------------------------def 转换标志():class 测试对象:def __str__(self): return STR表示def __repr__(self): return REPR表示obj 测试对象()print(f默认: {obj})print(f!s: {obj!s})print(f!r: {obj!r})print(f!a: {obj!a})name 张三\n李四print(f普通: {name})print(frepr: {name!r})转换标志()# -------------------------------------------------------------------# 6. 性能对比# -------------------------------------------------------------------def 格式化性能对比():name 张三age 28score 92.5迭代次数 1_000_000开始 time.perf_counter()for _ in range(迭代次数):_ f姓名: {name}, 年龄: {age}, 分数: {score}f耗时 time.perf_counter() - 开始开始 time.perf_counter()for _ in range(迭代次数):_ 姓名: %s, 年龄: %d, 分数: %.1f % (name, age, score)百分号耗时 time.perf_counter() - 开始开始 time.perf_counter()for _ in range(迭代次数):_ 姓名: {}, 年龄: {}, 分数: {}.format(name, age, score)format耗时 time.perf_counter() - 开始t string.Template(姓名: $name, 年龄: $age, 分数: $score)开始 time.perf_counter()for _ in range(迭代次数):_ t.substitute(namename, ageage, scorescore)template耗时 time.perf_counter() - 开始print(性能对比 ({:,} 次):.format(迭代次数))print(f f-string: {f耗时:.3f}秒 (最快))print(f % 格式化: {百分号耗时:.3f}秒)print(f str.format: {format耗时:.3f}秒)print(f Template: {template耗时:.3f}秒 (最慢))格式化性能对比()# -------------------------------------------------------------------# 7. 安全性用户输入与格式化# -------------------------------------------------------------------def 安全对比():恶意输入 {0.__class__.__mro__[2].__subclasses__()}t string.Template(用户输入: $user_input)result t.substitute(user_input恶意输入)print(fTemplate 安全处理用户输入: {result})print(\n安全建议:)print( - 普通场景: f-string)print( - 用户自定义模板: string.Template)print( - 日志记录: % 格式化延迟求值)安全对比()# -------------------------------------------------------------------# 8. 嵌套格式化与复杂表达式# -------------------------------------------------------------------def 嵌套与复杂格式化():value 123.456789for precision in range(1, 5):print(f精度 {precision}: {value:.{precision}f})score 85print(f状态: {通过 if score 60 else 未通过})items [1, 2, 3, 4, 5]print(f平方: {[x**2 for x in items]})name 张三age 28多行 (f姓名: {name}\nf年龄: {age}\nf信息: {name} 今年 {age} 岁)print(f\n多行 f-string:\n{多行})嵌套与复杂格式化()# -------------------------------------------------------------------# 9. 格式说明符完整参考# -------------------------------------------------------------------def 格式说明符参考():print(格式说明符完整参考:)print(语法: [[填充]对齐][符号][#][0][宽度][分组][.精度][类型])print(\n对齐: 左对齐 | 右对齐 | ^ 居中对齐)print(符号: 显示正负号 | - 仅负数 | 空格 正数留空)print(类型: d f % e b o x , _)print(f\n综合: {12345:010,d})print(f {12345.6789:10.2f})print(f {0.5:.2%})print(f {255:#010x})格式说明符参考()# -------------------------------------------------------------------# 10. 日志格式化策略# -------------------------------------------------------------------import loggingdef 日志格式化示例():user 张三action 登录logging.warning(用户 %s 执行 %s 操作, user, action)print( ✓ % 格式化: 延迟求值不浪费 CPU)t string.Template([$level] $time - $message)log_entry t.substitute(levelINFO,timedatetime.now().strftime(%H:%M:%S),message服务启动成功)print(f Template 日志: {log_entry})日志格式化示例()# # 总结# # 四种格式化方式对比:## 特性 | f-strings | str.format | % 格式化 | Template# ------------|------------|-------------|-----------|----------# 性能 | 最快 | 较慢 | 快 | 最慢# 可读性 | 最好 | 好 | 中等 | 好# 灵活性 | 高 | 高 | 中等 | 低# 安全性 | 中等 | 低 | 低 | 高# 延迟求值 | 否 | 否 | 是 | 否## 选择建议:# - 常规场景: f-string (最佳平衡)# - 日志记录: % 格式化 (logging 原生支持延迟求值)# - 用户模板: string.Template (安全)# - 国际化: gettext / Template# - 调试: f-string 说明符 (3.8)