Python3.8中使用f-strings调试


Posted in Python onMay 22, 2019

前言

我日常开发大概有98%的情况下会使用print来调试(别说pdb之类的, 根本不实用),通过在合适的位置插入print语句打印出要跟踪的表达式或者变量的值来确认问题。f-string让格式化这件事变得美观简单,但是依然对调试毫无帮助。

我举个例子:

s = 'A string'
value = 123

如果你想看运行时s和value的值分别是多少(PS: 这里演示的是常量,在实际代码执行中可能他们是表达式或者函数调用计算出来的,那时它们就是动态的了),可以在代码中加一行print打印一下它们:

s = 'A string'
value = 123
print(s, value) # 新插入的行

这样就能通过日志或者终端知道s和value是什么了。不过,这样做的问题是,通过输出对应s和value是不明确的,你需要非常清晰的了解代码逻辑;如果代码中有多个print,每个print都是2个参数,就麻烦了:

s = 'A string'
value = 123
print(s, value)
o = 'Other String'
rv = 234
print(o, rv) # 另外一个print

你还得用某种方法区分他们都是从哪行打印出来的:

s = 'A string'
value = 123
print(s, value, 'S')
o = 'Other String'
rv = 234
print(o, rv, 'Other')

这是我常用的方案,多加一个参数,通过第三项帮你确认分别是哪行打印出来的。

好的写法需要明确你要跟踪的变量和值的对应关系。可以这样写:

>>> print(f's={s!r}, value={value}')
s='A string', value=123
>>> print(f'o={o!r}, rv={rv}')
o='Other String', rv=234

大括号里面的除了有变量,后面还加个 !r ,它是一个转换标志(conversion flag),在过去的format格式化方法中也有。一共有三种转换标志,另外2个分别是 !a 和 !s ,我们感受一下:

>>> '{!a}'.format('哈哈') # 相当于 ascii('哈哈')
"'\\u54c8\\u54c8'"
>>> '{!s}'.format('哈哈') # 相当于 str('哈哈')
'哈哈'
>>> '{!r}'.format('哈哈') # 相当于 repr('哈哈')
"'哈哈'"

上面的例子中, {s!r} 就是对变量s执行 str(s) ,不用(不应该)这样写:

>>> print(f's={s}')
s=A string # 注意,没有引号,空格把值分开了,有多个值的话就不容易辨识
>>> print(f's="{s}"') # 不用`!r`需要手动加引号
s="A string"

不管怎么说,这样其实已经算不错的了,虽然当要打印的变量比较多的时候print语句非常长...

Python 3.8中f-strings的'='

这个功能还是看PyCON2019的闪电演讲看到的,f-strings的作者Eric V. Smith接受了Larry Hastings的意见实现了f-string的调试功能。本来是想另外一个转换标识 !d ,效果大概是这样:

value = 10
s = 'a string!'
print(f'{value!d}')
print(f'next: {value+1!d}')
print(f'{s!d}')
print(f'{s!d:*^20}')
print(f'*{value!d:^20}*')
# 输出
value=10
next: value+1=11
s='a string!'
'****s="A string"****'
*   value=10   *

也就是说,f-strings自动添加 变量名 + = ,而且支持补齐空位还能做表达式求值,如上例, {value+1!d} 表示计算 value+1 再打印出来。

不过后来作者和Guido讨论,改用了更灵活的 = 。现在已经合并到Python3.8,我们可以真实的试用了:

❯ ./python.exe
Python 3.8.0a4+ (heads/master:2725cb01d7, May 22 2019, 10:29:22)
...
>>> print(f'{s=}, {value=}')
s='A string', value=123
>>> print(f'{o=}, {rv=}')
o='Other String', rv=234
>>> print(f'{value / 3 + 15=}')
value / 3 + 15=56.0
>>> print(f'{s=:*^20}')
s=******A string******
>>> print(f'*{s=:^20}*')
*s=   A string   *

为啥我说用 = 更灵活呢,再看几个混合转换标识的例子:

>>> x = '哈哈'
>>> f'{x=}'
"x='哈哈'"
>>> f'{x=!s}'
'x=哈哈'
>>> f'{x=!r}'
"x='哈哈'"
>>> f'{x=!a}'
"x='\\u54c8\\u54c8'"
>>> f'{x=!s:^20}'
'x=     哈哈     '

就是说,DEBUG模式可以和转换标识一起用!

学到了吧?开始期待Python3.8了~

PS: 如果你看了PyCON的那个「Easier debugging with f-strings」的演讲(延伸阅读链接2),其中还是说用 !d ,其实演讲后第二天就改成了 = 了,要注意哈~

总结

以上所述是小编给大家介绍的Python3.8中使用f-strings调试,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Python 相关文章推荐
python 生成目录树及显示文件大小的代码
Jul 23 Python
python3读取MySQL-Front的MYSQL密码
May 03 Python
python使用pil库实现图片合成实例代码
Jan 20 Python
Python使用matplotlib绘制多个图形单独显示的方法示例
Mar 14 Python
Python自定义线程类简单示例
Mar 23 Python
python装饰器常见使用方法分析
Jun 26 Python
python中比较两个列表的实例方法
Jul 04 Python
python多环境切换及pyenv使用过程详解
Sep 27 Python
Python 列表的清空方式
Jan 13 Python
python tkinter 设置窗口大小不可缩放实例
Mar 04 Python
Python如何将模块打包并发布
Aug 30 Python
Vs Code中8个好用的python 扩展插件
Oct 12 Python
总结Python图形用户界面和游戏开发知识点
May 22 #Python
Python闭包和装饰器用法实例详解
May 22 #Python
Python进程间通信Queue消息队列用法分析
May 22 #Python
将python文件打包成EXE应用程序的方法
May 22 #Python
Python多线程threading模块用法实例分析
May 22 #Python
Python3之手动创建迭代器的实例代码
May 22 #Python
PyTorch搭建一维线性回归模型(二)
May 22 #Python
You might like
php中通过DirectoryIterator删除整个目录的方法
2015/03/13 PHP
ExtJS的FieldSet的column列布局
2009/11/20 Javascript
JavaScript NaN和Infinity特殊值 [译]
2012/09/20 Javascript
Jquery 选中表格一列并对表格排序实现原理
2012/12/15 Javascript
JavaScript检测弹出窗口是否已经关闭的方法
2015/03/24 Javascript
JavaScript通过setTimeout实时显示当前时间的方法
2015/04/16 Javascript
详谈LABJS按需动态加载js文件
2015/05/07 Javascript
jQuery获取checkboxlist的value值的方法
2015/09/27 Javascript
基于JavaScript实现智能右键菜单
2016/03/02 Javascript
利用vue-router实现二级菜单内容转换
2016/11/30 Javascript
jQuery插件FusionCharts实现的Marimekko图效果示例【附demo源码】
2017/03/24 jQuery
详谈Angular 2+ 的表单(一)之模板驱动型表单
2017/04/25 Javascript
React Native如何消除启动时白屏的方法
2017/08/08 Javascript
最全正则表达式总结:验证QQ号、手机号、Email、中文、邮编、身份证、IP地址等
2017/08/16 Javascript
js实现方块上下左右移动效果
2017/08/17 Javascript
vue router+vuex实现首页登录验证判断逻辑
2018/05/17 Javascript
JS实现HTML页面中动态显示当前时间完整示例
2018/07/30 Javascript
vue项目中在外部js文件中直接调用vue实例的方法比如说this
2019/04/28 Javascript
纯异步nodejs文件夹(目录)复制功能
2019/09/03 NodeJs
不刷新网页就能链接新的js文件方法总结
2020/03/01 Javascript
JavaScript如何实现图片处理与合成
2020/05/29 Javascript
[02:38]DOTA2超级联赛专访Loda 认为IG世界最强
2013/05/27 DOTA
python实现读取大文件并逐行写入另外一个文件
2018/04/19 Python
python实现将读入的多维list转为一维list的方法
2018/06/28 Python
Python 正则表达式匹配字符串中的http链接方法
2018/12/25 Python
HTML5 拖拽批量上传文件的示例代码
2018/03/28 HTML / CSS
关于html字符串正则判断和匹配的具体使用
2019/12/12 HTML / CSS
澳大利亚最大的百货公司:Myer
2018/12/21 全球购物
Dr.Jart+美国官网:韩国药妆品牌
2019/01/18 全球购物
Internal修饰符有什么含义
2013/07/10 面试题
生物制药自我鉴定
2014/01/25 职场文书
主题教育活动总结
2014/05/05 职场文书
国旗下的演讲稿
2014/05/08 职场文书
小学生节水倡议书
2015/04/29 职场文书
python周期任务调度工具Schedule使用详解
2021/11/23 Python
Golang原生rpc(rpc服务端源码解读)
2022/04/07 Golang