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 相关文章推荐
简单的Python2.7编程初学经验总结
Apr 01 Python
Python利用Beautiful Soup模块搜索内容详解
Mar 29 Python
Python数据结构之单链表详解
Sep 12 Python
TensorFlow在MAC环境下的安装及环境搭建
Nov 14 Python
python K近邻算法的kd树实现
Sep 06 Python
Python sklearn KFold 生成交叉验证数据集的方法
Dec 11 Python
使用python执行shell脚本 并动态传参 及subprocess的使用详解
Mar 06 Python
Python3 hashlib密码散列算法原理详解
Mar 30 Python
如何清空python的变量
Jul 05 Python
如何验证python安装成功
Jul 06 Python
python-地图可视化组件folium的操作
Dec 14 Python
python爬取某网站原图作为壁纸
Jun 02 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
Discuz! Passport 通行证整合
2008/03/27 PHP
php 文章采集正则代码
2009/12/28 PHP
注册页面之前先验证用户名是否存在的php代码
2012/07/14 PHP
处理(php-cgi.exe - FastCGI 进程超过了配置的请求超时时限)的问题
2013/07/03 PHP
PHP基于imagick扩展实现合成图片的两种方法【附imagick扩展下载】
2017/11/14 PHP
JavaScript中通过闭包解决只能取得包含函数中任何变量最后一个值的问题
2010/08/12 Javascript
jqGrid jQuery 表格插件测试代码
2011/08/23 Javascript
JavaScript高级程序设计 学习笔记 js高级技巧
2011/09/20 Javascript
JSON格式的时间/Date(2367828670431)/格式转为正常的年-月-日 格式的代码
2016/07/27 Javascript
聊一聊JS中的prototype
2016/09/29 Javascript
百度多文件异步上传控件webuploader基本用法解析
2016/11/07 Javascript
200行HTML+JavaScript实现年会抽奖程序
2019/01/22 Javascript
详解vue.js移动端配置flexible.js及注意事项
2019/04/10 Javascript
详解vue的双向绑定原理及实现
2019/05/05 Javascript
javascript将16进制的字符串转换为10进制整数hex
2020/03/05 Javascript
使用python统计文件行数示例分享
2014/02/21 Python
举例介绍Python中的25个隐藏特性
2015/03/30 Python
Python采用Django制作简易的知乎日报API
2016/08/03 Python
利用Python半自动化生成Nessus报告的方法
2019/03/19 Python
django之状态保持-使用redis存储session的例子
2019/07/28 Python
Pytorch 实现权重初始化
2019/12/31 Python
Python imutils 填充图片周边为黑色的实现
2020/01/19 Python
Python通过Pillow实现图片对比
2020/04/29 Python
如何安装并在pycharm使用selenium的方法
2020/04/30 Python
非常震撼的纯CSS3人物行走动画
2016/02/24 HTML / CSS
关于box-sizing的全面理解
2016/07/28 HTML / CSS
CSS3实现复选框动画特效示例代码
2016/09/27 HTML / CSS
英国家居装饰品、户外家具和玻璃器皿购物网站:Rinkit.com
2019/11/04 全球购物
工程造价管理专业大专生求职信
2013/10/06 职场文书
优良学风班申请材料
2014/02/13 职场文书
大三学习计划书范文
2014/05/02 职场文书
2014年党员承诺书范文
2014/05/20 职场文书
护理见习报告范文
2014/11/03 职场文书
小学语文教师年度考核个人总结
2015/02/05 职场文书
新教师个人总结
2015/02/06 职场文书
人身损害赔偿协议书
2016/03/22 职场文书