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单元测试框架unittest使用方法讲解
Apr 13 Python
Python的collections模块中的OrderedDict有序字典
Jul 07 Python
python中pandas.DataFrame排除特定行方法示例
Mar 12 Python
linecache模块加载和缓存文件内容详解
Jan 11 Python
Django中使用Celery的方法示例
Nov 29 Python
django实现类似触发器的功能
Nov 15 Python
Pytorch提取模型特征向量保存至csv的例子
Jan 03 Python
matplotlib jupyter notebook 图像可视化 plt show操作
Apr 24 Python
在django中form的label和verbose name的区别说明
May 20 Python
Python DES加密实现原理及实例解析
Jul 17 Python
完美解决torch.cuda.is_available()一直返回False的玄学方法
Feb 06 Python
Python文件的操作示例的详细讲解
Apr 08 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数组是否为空的代码
2011/09/08 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(五)
2014/06/23 PHP
浅谈php和.net的区别
2014/09/28 PHP
Yii核心组件AssetManager原理分析
2014/12/02 PHP
php模拟服务器实现autoindex效果的方法
2015/03/10 PHP
PHPStorm+XDebug进行调试图文教程
2016/06/13 PHP
EasySlider 基于jQuery功能强大简单易用的滑动门插件
2010/06/11 Javascript
return false;和e.preventDefault();的区别
2010/07/11 Javascript
jQuery插件开发详细教程
2014/06/06 Javascript
改变状态栏文字的js代码
2014/06/13 Javascript
基于jQuery倾斜打开侧边栏菜单特效代码
2015/09/15 Javascript
javascript实现列表切换效果
2016/05/02 Javascript
js中window.open的参数及注意注意事项
2016/07/06 Javascript
AngularJS入门教程之模块化操作用法示例
2016/11/02 Javascript
xmlplus组件设计系列之树(Tree)(9)
2017/05/02 Javascript
Node.js爬虫如何获取天气和每日问候详解
2019/08/26 Javascript
iSlider手机端图片滑动切换插件使用详解
2019/12/24 Javascript
[03:19]2016国际邀请赛中国区预选赛第四日TOP10镜头集锦
2016/07/01 DOTA
Python实现利用163邮箱远程关电脑脚本
2018/02/22 Python
django解决跨域请求的问题详解
2019/01/20 Python
python实现K近邻回归,采用等权重和不等权重的方法
2019/01/23 Python
Centos7 下安装最新的python3.8
2019/10/28 Python
Python爬虫入门有哪些基础知识点
2020/06/02 Python
详解Python 函数参数的拆解
2020/09/02 Python
移动端html5模拟长按事件的实现方法
2018/09/30 HTML / CSS
美特斯邦威官方商城:邦购网
2016/10/13 全球购物
加拿大最大的钻石商店:Peoples Jewellers
2018/01/01 全球购物
The Beach People美国:澳洲海滨奢华品牌
2018/07/05 全球购物
关于廉洁的广播稿
2014/01/30 职场文书
四群教育工作实施方案
2014/03/26 职场文书
学校爱国卫生月活动总结
2014/06/25 职场文书
行政求职信
2014/07/04 职场文书
2015年教师师德师风承诺书
2015/04/28 职场文书
原来闭幕词是这样写的呀!
2019/07/01 职场文书
Go Gin实现文件上传下载的示例代码
2021/04/02 Golang
python语言中pandas字符串分割str.split()函数
2022/08/05 Python