
咱先唠唠基础:f-string 是 Python 3.6 以后出的字符串格式化神器,比以前的%或者str.format()都方便 —— 直接在字符串里写变量,加个f前缀就行,比如f"我今年{age}岁"。但大部分人只用了它的基础功能,今天分享的 5 个进阶技巧,能让你写代码更简洁、调试更轻松,面试还能加分!
平时处理大数据的时候,比如统计全国用户量(好几亿)、计算文件大小(好几 GB),直接写数字又长又难读。比如123456789.1234,写成科学计数法1.23e+08就清爽多了,还能控制保留几位小数,避免数字乱糟糟。
格式超简单:f"{要格式化的数:.n e}"(注意小数点和e的位置),其中n是你想保留的小数位数。
# 场景1:统计用户量(大数)
user_count = 123456789.1234 # 假设是1.23亿用户
# 保留2位小数的科学计数法
print(f"总用户量:{user_count:.2e}") # 输出:总用户量:1.23e+08
# 保留3位小数的科学计数法
print(f"总用户量(精确版):{user_count:.3e}") # 输出:总用户量(精确版):1.235e+08
# 场景2:计算文件大小(带小数的大数)
file_size = 987654321.987 # 假设是987MB左右的文件
print(f"文件大小:{file_size:.1e} 字节") # 输出:文件大小:9.9e+08 字节f"{num:2.e}"(把小数点放反了),会报ValueError!正确是:.n e(小数点在前面)。:. -2e,会报错,小数位数必须是 0 或正整数。e和E:其实没啥大区别,e输出小写(1.23e+08),E输出大写(1.23E+08),根据需求选就行。如果同一个格式要重复用好几次(比如所有金额都要保留 2 位小数,所有百分比都要保留 1 位),每次都写:.2f或:.1%太麻烦了!把格式存成变量,改的时候只改变量,不用改每个 f-string,效率直接拉满。
先定义一个格式变量(比如fmt = ".2f"),然后在 f-string 里用{变量:{格式变量}}的写法调用。
# 场景:处理电商订单数据,所有金额都要保留2位小数
price_fmt = ".2f" # 定义金额格式:保留2位小数
discount_fmt = ".1%" # 定义折扣格式:保留1位百分比
# 订单1
phone_price = 5999 # 手机原价
phone_discount = 0.85 # 85折
print(f"手机原价:{phone_price:{price_fmt}} 元") # 输出:手机原价:5999.00 元
print(f"折扣:{phone_discount:{discount_fmt}}") # 输出:折扣:85.0%
print(f"折后价:{phone_price * phone_discount:{price_fmt}} 元n") # 输出:折后价:5099.15 元
# 订单2(复用同一个格式)
laptop_price = 8999.5
laptop_discount = 0.78
print(f"笔记本原价:{laptop_price:{price_fmt}} 元") # 输出:笔记本原价:8999.50 元
print(f"折扣:{laptop_discount:{discount_fmt}}") # 输出:折扣:78.0%
print(f"折后价:{laptop_price * laptop_discount:{price_fmt}} 元") # 输出:折后价:7019.61 元
# 想改格式?只改变量就行!比如所有金额保留1位小数
price_fmt = ".1f"
print(f"n改格式后 - 手机折后价:{phone_price * phone_discount:{price_fmt}} 元") # 输出:5099.2 元price_fmt写成"2.f"(小数点位置错),会报错,一定要跟直接写格式的规则一致。".2f"(小数格式)去格式化字符串变量(比如price = "5999"),会报ValueError: Unknown format code 'f' for object of type 'str'。生成文件路径时,Windows 用,Linux/macOS 用`/`,而且在普通字符串里是 “转义符”(比如n是换行),很容易出错。比如写C:Users小明file.txt,Python 会把U当成 Unicode 转义,直接报错!用 “原始字符串”(加r前缀)能避免转义问题,再结合 f-string 动态填用户名 / 文件名,完美!
格式:rf"路径{动态变量}路径"(r和f顺序随便,rf或fr都行),原始字符串会让变成普通字符,不转义。
# 场景1:Windows系统生成用户文件路径
username = "小明" # 动态用户名
filename = "report_2024.xlsx" # 动态文件名
# 错误写法:没加r,U会被当成Unicode转义,报错!
# print(f"C:Users{username}{filename}") # 报错:SyntaxError: (unicode error)
# 正确写法:加r,不转义
win_path = rf"C:Users{username}Documents{filename}"
print(f"Windows路径:{win_path}") # 输出:Windows路径:C:Users小明Documentsreport_2024.xlsx
# 场景2:Linux/macOS系统生成路径(虽然/不用转义,但加r也没问题,统一习惯)
linux_path = rf"/home/{username}/docs/{filename}"
print(f"Linux路径:{linux_path}") # 输出:Linux路径:/home/小明/docs/report_2024.xlsx
# 场景3:动态改文件名
new_filename = "data_2024.csv"
win_path_new = rf"C:Users{username}Documents{new_filename}"
print(f"新Windows路径:{win_path_new}") # 输出:新Windows路径:C:Users小明Documentsdata_2024.csvt变成制表符,n变成换行,路径直接乱了。/其实也能运行(Python 会自动转),但推荐用+r,符合系统习惯;Linux 别用,会报错。调试的时候,光打印变量值不够,比如print(area)只输出30.959,你可能忘了这是 “圆面积” 还是 “矩形面积”;而且数值太长(比如3.1415926535)看着累。用 f-string 控制格式,既能显示变量名,又能简化数值,调试效率翻倍!
格式:f"变量名:{变量:格式}",比如f"半径:{radius:.2f},面积:{area:.2f}",一眼就知道每个值对应啥,还能简化数值。
# 场景:计算圆的周长和面积,调试时看结果
pi = 3.1415926535
radius = 5.23 # 圆的半径(动态值)
# 计算
circumference = 2 * pi * radius # 周长
area = pi * radius ** 2 # 面积
# 基础调试:只打印值,看不清对应关系,数值也长
print("基础调试:", circumference, area) # 输出:基础调试: 32.86168132558529 85.1188617967359
# 进阶调试:用f-string控制格式,清晰多了
print(f"进阶调试 - 半径:{radius:.2f}(保留2位)") # 输出:进阶调试 - 半径:5.23(保留2位)
print(f"周长:{circumference:.1f}(保留1位)") # 输出:周长:32.9(保留1位)
print(f"面积:{area:.0f}(整数)") # 输出:面积:85(整数)
# 更灵活:调试列表数据
scores = [98.5, 87.8, 92.1, 76.3] # 学生成绩
print(f"n学生成绩(保留1位):")
for i, score in enumerate(scores, 1):
print(f"第{i}名:{score:.1f}") # 输出:第1名:98.5;第2名:87.8...f"{num:.5f}",如果只是快速看值,保留 1-2 位就够了,太复杂反而影响调试速度。f"半经:{radius:.2f}"(“经” 写错),虽然不报错,但调试时自己会看懵,尽量写对变量名。有时候你想控制变量的 “输出形态”:比如想让字符串带引号(方便看原始值)、想把中文转成 ASCII 码(避免乱码)。这时候!s、!r、!a就派上用场了,它们对应 Python 里的三个函数:str()、repr()、ascii(),不用单独写函数,直接在 f-string 里加个!就行。
转换符 | 对应函数 | 大白话作用 | 例子(变量:name = "小明",num = 123) | 输出结果 |
|---|---|---|---|---|
!s | str() | 转成 “普通字符串”,跟直接写变量差不多 |
| "小明"、"123" |
!r | repr() | 转成 “原始表示”,字符串会带引号 |
| "' 小明 '"、"123"(注意字符串多了引号) |
!a | ascii() | 转成 ASCII 码,非英文(比如中文)会转义 |
| "'u5c0fu660e'"(中文转成 Unicode 编码)、"123" |
# 定义测试变量
name = "小明" # 带中文的字符串
text = "HellonWorld" # 带转义符的字符串(n是换行)
num = 456 # 整数
# 1. !s:普通字符串(str())
print("!s 示例:")
print(f"名字:{name!s}") # 输出:名字:小明(跟直接写{name}一样)
print(f"数字:{num!s}") # 输出:数字:456(整数转字符串)
# 2. !r:原始表示(repr()),适合调试看原始值
print("n!r 示例:")
print(f"名字:{name!r}") # 输出:名字:'小明'(字符串带单引号)
print(f"文本:{text!r}") # 输出:文本:'HellonWorld'(n没转成换行,保留原始样子)
# 3. !a:ASCII码(ascii()),适合非英文环境避免乱码
print("n!a 示例:")
print(f"名字:{name!a}") # 输出:名字:'u5c0fu660e'(中文转Unicode编码)
print(f"文本:{text!a}") # 输出:文本:'HellonWorld'(英文不变,n保留)n),却用了!s,结果n直接转成换行,看不到原始样子。uXXXX编码,反而看不懂,只有在非中文环境(比如 Linux 服务器)才需要用。这里整理了大家用 f-string 时最容易犯的错,每个错都附 “错误代码” 和 “解决办法”,保证你少踩坑!
错误类型 | 错误代码示例 | 报错信息 | 解决办法 |
|---|---|---|---|
格式符顺序错 |
| ValueError: Invalid format specifier | 把 |
变量没定义 |
| NameError: name 'age' is not defined | 先定义变量 |
类型不匹配 |
| ValueError: Unknown format code 'f' for object of type 'str' | 先把字符串转成数字: |
Windows 路径没加 r |
| SyntaxError: (unicode error) | 加 r 前缀: |
转换符位置错 |
| SyntaxError: invalid syntax | 只能用一个转换符,选需要的: |
f-string 是 Python 面试的高频考点,尤其是进阶用法,这里整理了 5 个常考题,答案都带代码示例,面试时这么说绝对加分!
答:很简单,用:.n e的格式就行,n是小数位数。比如处理 1 亿的用户量,想保留 2 位小数:
user_count = 123456789
print(f"总用户量:{user_count:.2e}") # 输出:总用户量:1.23e+08如果想保留 3 位,就把.2e改成.3e,特别方便。
答:因为如果多个地方用同一个格式(比如所有金额都保留 2 位小数),存成变量能复用,改的时候只改变量,不用改每个 f-string。比如处理电商订单:
# 定义格式变量
price_fmt = ".2f"
# 复用格式
phone_price = 5999
laptop_price = 8999.5
print(f"手机:{phone_price:{price_fmt}}元") # 输出:5999.00元
print(f"笔记本:{laptop_price:{price_fmt}}元") # 输出:8999.50元
# 想改格式,只改price_fmt就行
price_fmt = ".1f"
print(f"手机(改格式):{phone_price:{price_fmt}}元") # 输出:5999.0元答:好处是避免的转义问题(比如 Windows 路径里的U、t)。比如想生成C:Users小明,如果没加 r:
# 错误例子:没加r,U触发Unicode转义,报错
username = "小明"
print(f"C:Users{username}") # 报错:SyntaxError
# 正确例子:加r,不转义
print(rf"C:Users{username}") # 输出:C:Users小明答:三个都是转换变量输出形态的,对应不同场景:
f"名字:{name!s}",输出 “名字:小明”。f"文本:{text!r}",能看到隐藏的n。f"名字:{name!a}",输出'u5c0fu660e'。答:直接 print 变量只能看到值,分不清对应关系,数值也可能太长。用 f-string 能同时显示 “变量名” 和 “控制格式”,比如调试圆的面积:
# 直接print:看不清对应关系
radius = 5.23
area = 3.1415 * radius**2
print(area) # 输出:85.118...(不知道这是啥值)
# f-string调试:清晰
print(f"半径:{radius:.2f},面积:{area:.1f}") # 输出:半径:5.23,面积:85.1一眼就知道每个值对应啥,数值也简化了,调试效率高很多。
这 5 个 f-string 技巧看着简单,但用好了能省不少事:科学计数法让大数更清爽,格式变量减少重复代码,原始字符串解决路径问题,调试格式让 bug 好找,!s/!r/!a 控制输出形态。
建议你现在就打开 Python 编辑器,把以前用%或format()的代码改成 f-string,试试这些技巧 —— 用一次就知道有多香!后续遇到其他 f-string 问题,也可以回头看看这篇文章的避坑指南~
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。