《Effective Python》第2章 字符串和切片操作——Python 字符串格式化的现代选择f-strings
引言
本篇博客基于学习《Effective Python》第三版 Chapter 2: Strings and Slicing 的 Item 11 “Prefer Interpolated F-Strings Over C-style Format Strings and str.format” 的总结与延伸。
字符串格式化是 Python 编程中的常见操作,用于动态生成可读性高的文本输出。从早期的 C 风格格式化(% 运算符),到 str.format 方法,再到 Python 3.6 引入的 f-strings
,Python 的字符串格式化方式经历了显著的演进。f-strings
以其简洁、直观和强大的功能,成为现代 Python 开发者的首选。本文将深入探讨 f-strings
的优势、语法、应用场景以及常见误区,帮助读者全面掌握这一工具,并在实际项目中做出更优的选择。
从历史到现代:Python 字符串格式化的演进
为什么需要字符串格式化?
字符串格式化是将变量或表达式嵌入到字符串中的过程,广泛应用于日志记录、用户界面输出、报表生成等领域。早期,Python 提供了多种格式化方式,每种方式都在特定场景下有其优势,但也存在局限性。
C 风格格式化(%)的局限性
C 风格格式化使用 % 运算符,例如 "%s is %d years old" % (name, age)
。这种方式简单,但问题明显:
- 可读性差:当参数较多时,代码难以快速理解,容易出错。
- 类型限制:需要显式指定格式说明符(如 %s、%d),一旦类型不匹配,就会抛出异常。
- 复杂场景支持不足:难以处理嵌套结构或动态格式化需求。
例如:
name = "Alice"
age = 30
print("%s is %d years old" % (name, age)) # 输出:Alice is 30 years old
当参数列表变长或格式化需求复杂时,代码维护变得困难。
str.format 方法的改进与不足
Python 2.6 引入的 str.format 方法通过占位符 {}
改进了格式化体验,例如 "{} is {} years old".format(name, age)
。它支持按索引或关键字指定参数,灵活性更高:
print("{0} is {1} years old".format(name, age)) # 按索引
print("{name} is {age} years old".format(name=name, age=age)) # 按关键字
然而,str.format 也有缺点:
- 冗长:需要显式调用 format 方法,代码显得啰嗦。
- 性能开销:相较于
f-strings
,解析和执行速度稍慢。 - 复杂性:嵌套格式化或动态表达式仍需额外处理。
f-strings
的诞生与核心优势
Python 3.6 引入的 f-strings
(PEP 498)彻底革新了字符串格式化。通过在字符串前添加 f
前缀,开发者可以直接在字符串中嵌入变量或表达式:
print(f"{name} is {age} years old") # 输出:Alice is 30 years old
f-strings
的优势包括:
- 简洁直观:变量和表达式直接嵌入字符串,无需额外的调用或占位符。
- 高性能:
f-strings
在编译时解析,执行效率高于 str.format。 - 灵活性:支持任意 Python 表达式,适应复杂格式化需求。
Python 字符串格式化方式对比
C 风格格式化 (%) | str.format | F-字符串 |
---|---|---|
简单但局限 | 灵活但冗长 | 简洁高效 |
类型严格 | 性能稍逊 | 支持表达式 |
可读性差 | 复杂场景有限 | 动态灵活 |
f-strings
的语法与强大功能
f-strings
的基本语法是什么?
f-strings
的基本语法是在字符串前加 f
或 F
前缀,并在字符串中使用 {}
嵌入变量或表达式。例如:
value = 42
print(f"The answer is {value}") # 输出:The answer is 42
这种语法直观,消除了 C 风格格式化或 str.format 的复杂性。
动态表达式支持:超越静态替换
f-strings
的强大之处在于支持任意 Python 表达式。例如:
x = 10
y = 20
print(f"Sum: {x + y}, Product: {x * y}") # 输出:Sum: 30, Product: 200
甚至可以在 f-strings
中调用函数或执行复杂计算:
def greet(name):return f"Hello, {name}!"
print(f"Greeting: {greet('Alice')}") # 输出:Greeting: Hello, Alice!
这种能力让 f-strings
在动态生成文本时极具灵活性。
格式化控制:精度、对齐与填充
f-strings
支持精细的格式控制,例如控制浮点数精度、字符串对齐等:
price = 19.999
print(f"Price: ${price:.2f}") # 输出:Price: $19.99
name = "Alice"
print(f"Name: {name:>10}") # 输出:Name: Alice
格式说明符(如 .2f
、:>10
)与 str.format 类似,但更直观。例如,:<10
表示左对齐,:^10
表示居中对齐。
常见误区:滥用复杂表达式与性能陷阱
尽管 f-strings
支持复杂表达式,但滥用可能导致代码难以维护。例如:
# 不推荐:复杂表达式降低可读性
print(f"Result: {compute_complex_value(x, y, z) * factor + offset}")
更好的做法是将复杂逻辑提前计算:
result = compute_complex_value(x, y, z) * factor + offset
print(f"Result: {result}")
此外,f-strings
在循环中重复构造可能影响性能。例如:
# 不推荐:重复构造 `f-strings`
for i in range(1000):log.append(f"Item {i}")
更优的做法是批量处理或使用列表推导式:
log.extend(f"Item {i}" for i in range(1000))
示意图:f-strings
语法结构
f"普通文本 {表达式:格式控制} 普通文本 {表达式} 普通文本"
| | | | | |
前缀 表达式 格式控制 文本 表达式 文本
f-strings
的实际应用与案例分析
f-strings
在实际开发中如何发挥作用?
f-strings
在日志记录、数据报表和模板化等场景中表现尤为出色。以下通过三个案例展示其应用。
案例 1:日志记录中的动态格式化
在日志记录中,f-strings
可以动态生成详细的日志信息。例如:
import datetime
user = "Alice"
action = "login"
timestamp = datetime.datetime.now()
print(f"[{timestamp}] User {user} performed {action}") # 输出:[2025-05-12 10:00:00] User Alice performed login
相比 str.format,f-strings
代码更简洁,且支持直接嵌入 timestamp 等动态值。
案例 2:数据报表中的格式控制
在生成数据报表时,f-strings
的格式控制功能非常实用。例如,生成一个价格报表:
items = [("Apple", 1.99), ("Banana", 0.99), ("Orange", 2.49)]
for name, price in items:print(f"{name:<10} | ${price:>6.2f}")
输出:
Apple | $ 1.99
Banana | $ 0.99
Orange | $ 2.49
通过 :<10
和 :>6.2f
,实现字符串左对齐和价格右对齐,格式整齐。
案例 3:多语言支持与模板化
在多语言应用中,f-strings
可与字典结合实现动态模板化。例如:
translations = {"en": {"greeting": "Hello, {name}!"},"es": {"greeting": "¡Hola, {name}!"}
}
lang = "es"
name = "Alice"
print(f"{translations[lang]['greeting'].format(name=name)}") # 传统方式
print(f"Hello, {name}!") # `f-strings`简化
虽然此处 f-strings
未直接使用多语言模板,但其灵活性允许与模板系统无缝集成。
误区提醒:如何避免 f-strings
的过度复杂化
一个常见错误是在 f-strings
中嵌入过多逻辑,例如:
# 不推荐:复杂逻辑嵌入
print(f"Total: {sum([x['price'] for x in items if x['category'] == 'fruit'])}")
更好的做法是提前计算:
total = sum(x['price'] for x in items if x['category'] == 'fruit')
print(f"Total: {total}")
此外,避免在 f-strings
中嵌入用户输入,防止安全风险(如格式化注入)。
总结
总结 f-strings
的核心优势与适用场景
f-strings
以其简洁、高效和灵活的特性,成为 Python 字符串格式化的首选工具。相比 C 风格格式化和 str.format,f-strings
在可读性、性能和功能上全面领先,特别适合日志记录、报表生成和动态文本生成等场景。通过支持动态表达式和格式控制,f-strings
能应对复杂的格式化需求。
对比其他格式化方法的适用场景
尽管 f-strings
是现代 Python 的推荐选择,某些场景下其他方法仍有价值:
- C 风格格式化:在兼容旧代码或极简单的格式化场景中仍可使用,但不推荐新项目。
- str.format:在需要动态生成模板(例如多语言支持)时,str.format 的占位符机制可能更适合。
- 模板字符串(string.Template):在处理用户输入或需要严格安全控制的场景中更为安全。
建议:如何在项目中逐步迁移到 f-strings
对于现有项目,建议:
- 优先新代码:在新开发的模块中使用
f-strings
。 - 逐步重构:在重构旧代码时,将 C 风格格式化和 str.format 替换为
f-strings
。 - 性能测试:在性能敏感场景下,测试
f-strings
与 str.format 的差异。 - 培训团队:确保团队熟悉
f-strings
的语法和最佳实践。
总结
本文结合《Effective Python》第三版 Item 11 的内容,探讨了 Python f-strings
的起源、语法、优势和实际应用,希望这篇文章能帮助你更好地掌握 f-strings
,并在 Python 开发中提升代码质量与效率!后续我会继续分享更多关于《Effective Python》精读笔记系列,参考我的代码库 effective_python_3rd,一起交流成长!
相关文章:
《Effective Python》第2章 字符串和切片操作——Python 字符串格式化的现代选择f-strings
引言 本篇博客基于学习《Effective Python》第三版 Chapter 2: Strings and Slicing 的 Item 11 “Prefer Interpolated F-Strings Over C-style Format Strings and str.format” 的总结与延伸。 字符串格式化是 Python 编程中的常见操作,用于动态生成可读性高的…...

企业报表平台如何实现降本增效
一、你的企业是否正被这些问题拖累? 财务还在手动汇总各门店的Excel销售数据;市场部总抱怨“客户分析全靠拍脑袋”;仓库突然发现爆款断货,但上周的报表显示库存充足…… 这些场景你是否熟悉?数据散落在ERP、E…...

Ollama+OpenWebUI+docker完整版部署,附带软件下载链接,配置+中文汉化+docker源,适合内网部署,可以局域网使用
前言: 因为想到有些环境可能没法使用外网的大模型,所以可能需要内网部署,看了一下ollama适合小型的部署,所以就尝试了一下,觉得docker稍微简单一点,就做这个教程的,本文中重要的内容都会给下载…...
git push 报错:send-pack: unexpected disconnect while reading sideband packet
背景 新建了一个仓库,第一次push 代码文件,文件中有一个依赖的jar,有80MB,结果push的时候报错。 错误信息 error: RPC failed; HTTP 500 curl 22 The requested URL returned error: 500 send-pack: unexpected disconnect whi…...
考研英一真题学习笔记 2018年
2018 年全国硕士研究生招生考试 英语 (科目代码:201) Section Ⅰ Use of English Directions: Read the following text. Choose the best word(s) for each numbered blank and mark A, B, C or D on the ANSWER SHEET. (10 points) Trust i…...

ultralytics中tasks.py---parse_model函数解析
一、根据scale获取对应的深度、宽度和最大通道数 具体例如yaml文件内容如下: depth=0.33,那么重复的模块例如C2f原本重复次数是3,6,6,3,那么T对应的模型重复次数就是三分之一即1,1,2,1次。这个在后面定义的: width=0.25,max_channels=1024 原本c2=64,但经过make_div…...
Java知识框架
一、Java 基础语法 1. 基础语法 数据类型 基本类型:int, double, boolean, char 等 引用类型:String, 数组, 对象 变量与常量 final 关键字 作用域(局部变量、成员变量) 运算符 算术、逻辑、位运算 三元运算符 ? : 控制…...

2024年业绩增速大幅回退,泸州老窖未能“重回前三”
撰稿|行星 来源|贝多财经 回望过去的2024年,受制于购买力与消费需求的持续疲软,白酒行业的发展面临诸多复杂性与不确定性,“量价齐跌”犹如笼罩在各大企业头顶的一片阴云。 正如巴菲特所言:“当潮水退去时,才知道谁在…...

院校机试刷题第二天:1479 01字符串、1701非素数个数
一、1479 01字符串 1.题目描述 2.解题思路 方法一:暴力法 模拟过程,列出几个数据来a[1]1, a[2]2, a[3]3, a[4]5以此类推,这就是斐波那契数列,每一项都等于前两项之和,确定好a[1], a[2]即可。 方法二:动…...
【Vue.js 的核心魅力:深入理解声明式渲染】
Vue.js 的核心魅力:深入理解声明式渲染 在现代前端框架的浪潮中,Vue.js 以其轻量、易学、高效的特点赢得了广大开发者的青睐。其核心魅力之一,便是其优雅的**声明式渲染 (Declarative Rendering)**机制。理解声明式渲染不仅能帮助我们更好地…...

制作一款打飞机游戏48:敌人转向
射击功能 有一个重要的功能我们还没实现,那就是射击。目前,敌人还不能射击,这显然是不行的。因此,我们决定添加一个射击命令,暂时用一个显示圆圈的方式来表示射击动作。 编程语言的调试 有趣的是,我们创…...
鸿蒙OSUniApp打造多功能图表展示组件 #三方框架 #Uniapp
使用UniApp打造多功能图表展示组件 在当前移动应用开发领域,数据可视化已成为不可或缺的一部分。无论是展示销售数据、用户增长趋势还是其他业务指标,一个优秀的图表组件都能有效提升用户体验。UniApp作为一款跨平台开发框架,如何在其中实现…...
Chrome浏览器实验性API computePressure的隐私保护机制如何绕过?
一、computePressure API 设计原理与隐私保护机制 1.1 API 设计目标 computePressure是W3C提出的系统状态监控API,旨在: • 提供系统资源状态的抽象指标(非精确值) • 防止通过高精度时序攻击获取用户指纹 • 平衡开发者需求与用户隐私保护 1.2 隐私保护实现方式 // 典…...

RK3588 串行解串板,支持8路GMSL相机
RK3588 支持的 GMSL 相机接入数量取决于所使用的解串板型号及配置方案: xcDeserializer3.0 解串板 可接入最多 8 路 2M GMSL2 相机1。 xcDeserializer4.0 解串板 支持 4 路 2M GMSL2 相机1。 边缘计算盒解决方案 部分商用方案可实现 4 或 8…...

OracleLinux7.9-ssh问题
有套rac环境,db1主机无法ssh db1和db1-priv,可以ssh登录 db2和db2-priv [rootdb1 ~]# ssh db1 ^C [rootdb1 ~]# ssh db2 Last login: Wed May 14 18:25:19 2025 from db2 [rootdb2 ~]# ssh db2 Last login: Wed May 14 18:25:35 2025 from db1 [rootdb2…...

手机换IP真的有用吗?可以干什么?
在当今数字化时代,网络安全和个人隐私保护日益受到重视。手机作为我们日常生活中不可或缺的工具,其网络活动痕迹往往通过IP地址被记录和追踪。那么,手机换IP真的有用吗?它能为我们带来哪些实际好处?本文将为你一一解答…...
提示词设计模板(基于最佳实践)
1. 任务清晰化 模糊指令 ➜ 明确指令 ❌ "写一篇关于环保的文章" ✅ *"列出5种城市环保措施,并分别说明其对减少碳排放的影响(要求:数据支持案例)"* 2. 任务步骤化 案例:策划线上营销活动 1.…...

如何实现一个运动会计分系统?(C语言版)
一、需求分析 设计一个运动会计分系统,计分信息包括参加学校,参与项目,性别,名次个数,各个学校获得名次信息。该系统具有以下功能 数据录入: 链表或结构体数组组织数据数据报表: 依照规定的报表格式对数据打印报表数据排序: 按照要求对数据进行统计,含简单统计及综合统计…...
《P4391 [BalticOI 2009] Radio Transmission 无线传输 题解》
题目描述 给你一个字符串 s1,它是由某个字符串 s2 不断自我连接形成的(保证至少重复 2 次)。但是字符串 s2 是不确定的,现在只想知道它的最短长度是多少。 输入格式 第一行一个整数 L,表示给出字符串的长度。…...
tocmat 启动怎么设置 jvm和gc
在生产环境中部署 Java Web 应用时,我们经常需要给 Tomcat 设置 JVM 参数和 GC 策略,以提高性能、稳定性和可观察性。以下是完整教程: 一、Tomcat 设置 JVM 启动参数的方式 1. 修改 startup 脚本(推荐) 以 Linux 系统…...
[思维模式-37]:什么是事?什么是物?什么事物?如何通过数学的方法阐述事物?
一、基本概念 1、事(Event) “事”通常指的是人类在社会生活中的各种活动、行为、事件或情况,具有动态性和过程性,强调的是一种变化、发展或相互作用的流程。 特点 动态性:“事”往往涉及一系列的动作、变化和发展过程。例如&a…...
面向对象设计模式之代理模式详解
文章目录 面向对象设计模式之代理模式详解面向对象思想:现代软件开发的基石代理模式:巧妙的中间层设计JavaScript 语法点与代理模式的结合JavaScript 实现代理模式示例代理模式的应用场景 面向对象设计模式之代理模式详解 在现代软件开发的浩瀚领域中&a…...
C++【STL】(2)string
C【STL】string用法扩展 1. assign:为字符串赋新值 用于替换字符串内容,支持多种参数形式。 常用形式: // 用另一个字符串赋值 str.assign("Hello World");// 用另一个字符串的子串(从第6个字符开始,取5…...

嵌入式学习笔记 - STM32 ADC,多重转换,内部参考电压,过采样,逐次逼近原理,采样时间
一 多个ADC器件,多重转换速率 每个型号MCU通常由多个ADC器件,比如STM32F4有三个ADC器件,每个ADC器件有一个最大转换速率,一般为2.4Mhz,即一个ADC器件每秒最多转换2.4M次,两次转换之间需要有时间间隔&#…...

团结引擎 1.5.0 发布,抖音小游戏平台即将开放、Shader Graph功能新增…引擎能力再提升!
「团结引擎 1.5.0」来啦!本次技术更新的内容,涵盖了小游戏、团结引擎车机版、OpenHarmony、Shader Graph、Muse Chat、Hub&License、代码升级、Digital Asset Manager for Tuanjie、团结官方开源车模 Sample 几大方向。 小游戏 在 Tuanjie 1.5.0 版…...
如何下载 Microsoft SQL Server Management Studio 2019
SQL Server Management Studio 是什么,为什么你需要它 SSMS 是 Microsoft 用于管理 SQL Server 环境的主要工具。它为 Windows 用户提供了一个图形用户界面,本质上是数据库管理员和开发人员处理 SQL Server 的指挥中心。重点是——尽管你可能认为它与 SQL Server 捆绑在一起…...
【SSL部署与优化】HTTP/2与HTTPS的协同效应
HTTP/2与HTTPS的协同效应:为何HTTP/2强制要求TLS 1.2? HTTP/2是HTTP协议的现代升级版,旨在通过多路复用、头部压缩等技术提升性能。然而,HTTP/2的设计与部署与HTTPS(TLS加密)紧密相关,甚至强制…...

如何配置activemq,支持使用wss协议连接。
1、到阿里云申请一个证书,通过后下载jks证书。 2、配置activemq: 打开activemq安装目录中“conf/activemq.xml”,增加以下记录: <transportConnectors> <transportConnector name"wss" uri"…...
GO语言内存管理结构
文章目录 1、内存分区1.1、栈(Stack)1.2、堆(Heap) 2、堆内存管理结构2.1、内存分配器(MCache → MArena → MSpan → MHeap)2.2、大小分类(Size Class)2.3、分配流程 3、垃圾回收&a…...

初学c语言14(指针6)
一.sizeof和strlen的对比 1.sizeof 操作符,计算变量所占空间大小 2.strlen 库函数,函数原型为: 求的是字符串的长度,统计的是“\0”之前的字符个数 二.指针和笔试题解析 补充:数组名的意义 1.sizeof(数组名) 这…...