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 ElementTree 基本读操作示例
Apr 09 Python
状态机的概念和在Python下使用状态机的教程
Apr 11 Python
解决Python中字符串和数字拼接报错的方法
Oct 23 Python
Python爬虫包BeautifulSoup学习实例(五)
Jun 17 Python
Python实现随机创建电话号码的方法示例
Dec 07 Python
python中的TCP(传输控制协议)用法实例分析
Nov 15 Python
解决python中的幂函数、指数函数问题
Nov 25 Python
python实现双色球随机选号
Jan 01 Python
Windows下python3安装tkinter的问题及解决方法
Jan 06 Python
如何卸载python插件
Jul 08 Python
python解决OpenCV在读取显示图片的时候闪退的问题
Feb 23 Python
python3 字符串str和bytes相互转换
Mar 23 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
从零开始学YII2框架(一)通过Composer安装Yii2框架
2014/08/20 PHP
PHP处理Json字符串解码返回NULL的解决方法
2014/09/01 PHP
3种方法轻松处理php开发中emoji表情的问题
2016/07/18 PHP
php 修改上传文件大小限制实例详解
2016/10/23 PHP
javascript小数计算出现近似值的解决办法
2010/02/06 Javascript
js控制table合并具体实现
2014/02/20 Javascript
ExtJS4给Combobox设置列表中的默认值示例
2014/05/02 Javascript
jQuery表单域选择器用法分析
2015/02/10 Javascript
jQuery中fadein与fadeout方法用法示例
2016/09/16 Javascript
Highcharts+NodeJS搭建数据可视化平台示例
2017/01/01 NodeJs
详解AngularJs路由之Ui-router-resolve(预加载)
2017/06/13 Javascript
js装饰设计模式学习心得
2018/02/17 Javascript
Vue.js中使用iView日期选择器并设置开始时间结束时间校验功能
2018/08/12 Javascript
微信小程序chooseImage的用法(从本地相册选择图片或使用相机拍照)
2018/08/22 Javascript
JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法详解【普里姆算法】
2018/12/13 Javascript
了解JavaScript中let语句
2019/05/30 Javascript
浅谈element中InfiniteScroll按需引入的一点注意事项
2020/06/05 Javascript
Vue3 实现双盒子定位Overlay的示例
2020/12/22 Vue.js
解析Python中的变量、引用、拷贝和作用域的问题
2015/04/07 Python
django 类视图的使用方法详解
2019/07/24 Python
Python Collatz序列实现过程解析
2019/10/12 Python
Python如何将将模块分割成多个文件
2020/08/04 Python
IWOOT美国:新奇的小玩意
2018/04/27 全球购物
维多利亚的秘密官方网站:Victoria’s Secret
2018/10/24 全球购物
英国天然抗衰老护肤品品牌:Nakin Skin Care
2019/04/16 全球购物
介绍一下Ruby中的对象,属性和方法
2012/07/11 面试题
介绍一下SOA和SOA的基本特征
2016/02/24 面试题
自动化专业职业生涯规划书范文
2014/01/16 职场文书
2015年元旦文艺汇演主持词
2014/03/26 职场文书
法人授权委托书
2014/04/03 职场文书
党员政治学习材料
2014/05/14 职场文书
书法社团活动总结
2015/05/07 职场文书
酒店厨房管理制度
2015/08/06 职场文书
家长会后的感想
2015/08/11 职场文书
有趣的二维码:使用MyQR和qrcode来制作二维码
2021/05/10 Python
vue中利用mqtt服务端实现即时通讯的步骤记录
2021/07/01 Vue.js