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基础教程之常用运算符
Aug 29 Python
利用Python爬取微博数据生成词云图片实例代码
Aug 31 Python
Python基于回溯法子集树模板解决数字组合问题实例
Sep 02 Python
Python subprocess模块常见用法分析
Jun 12 Python
漂亮的Django Markdown富文本app插件的实现
Jan 02 Python
python用opencv批量截取图像指定区域的方法
Jan 24 Python
Python利用lxml模块爬取豆瓣读书排行榜的方法与分析
Apr 15 Python
Python利用PyExecJS库执行JS函数的案例分析
Dec 18 Python
TensorFlow加载模型时出错的解决方式
Feb 06 Python
Python matplotlib读取excel数据并用for循环画多个子图subplot操作
Jul 14 Python
Python如何创建装饰器时保留函数元信息
Aug 07 Python
Python使用lambda抛出异常实现方法解析
Aug 20 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 array_reverse 以相反的顺序返回数组实例代码
2017/04/11 PHP
ASP小贴士/ASP Tips javascript tips可以当桌面
2009/12/10 Javascript
基于jquery的direction图片渐变动画效果
2010/05/24 Javascript
基于jquery & json的省市区联动代码
2012/06/26 Javascript
js 利用image对象实现图片的预加载提高访问速度
2013/03/29 Javascript
jquery ajax传递中文参数乱码问题及解决方法说明
2014/02/07 Javascript
jQuery实现contains方法不区分大小写的方法
2015/02/13 Javascript
jQuery 实现评论等级好评差评特效
2016/05/06 Javascript
jQuery实现下拉框功能实例代码
2016/05/06 Javascript
js实现可控制左右方向的无缝滚动效果
2016/05/29 Javascript
浅谈angular懒加载的一些坑
2016/08/20 Javascript
Vue2.0设置全局样式(less/sass和css)
2017/11/18 Javascript
jQuery实现当拉动滚动条到底部加载数据的方法分析
2019/01/24 jQuery
[00:32]2018DOTA2亚洲邀请赛Newbee出场
2018/04/03 DOTA
python爬虫入门教程--HTML文本的解析库BeautifulSoup(四)
2017/05/25 Python
python 实现对文件夹中的图像连续重命名方法
2018/10/25 Python
python交换两个变量的值方法
2019/01/12 Python
python 读取dicom文件,生成info.txt和raw文件的方法
2019/01/24 Python
Python人脸识别第三方库face_recognition接口说明文档
2019/05/03 Python
Python爬取腾讯视频评论的思路详解
2019/12/19 Python
css3中用animation的steps属性制作帧动画
2019/04/25 HTML / CSS
HTML5 LocalStorage 本地存储刷新值还在
2017/03/10 HTML / CSS
Hunkemöller瑞士网上商店:欧洲最大的内衣品牌之一
2018/12/03 全球购物
SmartBuyGlasses比利时:购买品牌太阳镜和眼镜
2019/08/09 全球购物
大学生求职自荐信
2013/12/12 职场文书
少先队学雷锋活动总结范文
2014/03/09 职场文书
教育英语专业毕业生的求职信
2014/03/13 职场文书
2014年幼儿园教研工作总结
2014/12/04 职场文书
大班下学期幼儿评语
2014/12/30 职场文书
升学宴家长答谢词
2015/09/29 职场文书
你会写请假条吗?
2019/06/26 职场文书
创业计划书之服装
2019/10/07 职场文书
Python基础之数据类型知识汇总
2021/05/18 Python
MySQL 常见存储引擎的优劣
2021/06/02 MySQL
Java数组与堆栈相关知识总结
2021/06/29 Java/Android
配置Kubernetes外网访问集群
2022/03/31 Servers