为什么我要强调从 Python 3.6 开始呢? 我认为在这之前的版本无论是性能和语法完整性都不够, 在 Python 3.6 时添加了异步生成器, 异步推导语法, 非常实用的 Path 模块等等, 另外一个很重要的是添加了 f-strings 语法, 大家用了就会发现根本停不下来. 本文就和大家聊聊这个神奇的 f-strings.
f-string 是格式化字符串的新语法. 与其他格式化方式相比, 它们不仅更易读, 更简洁, 不易出错, 而且速度更快! 我们首先了解下可视化字符串语法的历史
1: %-formatting
最早的格式化是用 %(百分号), 它这么用:
% 符号前面使用一个字符串作为模板, 模板中有标记格式的占位符号. 占位符控制着显示的格式, 这里用的 %s 表示格式化成字符串, 另外常用的是 %d (十进制整数), %f (浮点数).
格式化语法也可以格式化多个变量, 需要把变量用括号括起来:
另外也支持使用字典的形式:
这种用法一直到现在仍然被使广泛使用, 但是其实它是一种不被提倡使用的语法 (我初 Python 学习时, 就提过). 主要是当要格式化的参数很多时, 可读性很差, 还容易出错 (数错占位符的数量), 也不灵活, 举个例子, name 这个变量要在格式化时用 2 次, 就要传入 2 次.
2. str.format()
从 Python 2.6 开始, 新增了一种格式化字符串的函数 str.format() , 基本语法是通过 {} 和 : 来代替以前的 % .format 函数支持通过位置, 关键字, 对象属性和下标等多种方式使用, 不仅参数可以不按顺序, 也可以不用参数或者一个参数使用多次. 并且可以通过对要转换为字符串的对象的 __format __ 方法进行扩展.
通过位置访问:
通过关键字访问:
通过对象属性访问:
通过下标访问:
可以感受到 format 函数极大的扩展了格式化功能. 但是当处理多个参数和更长的字符串时, str.format() 的内容仍然可能非常冗长, 除了定义参数变量, 需要把这些变量写进 format 方法里面.
3. f-Strings
现在好了, Python 3.6 新增了 f-strings, 这个特性叫做 字面量格式化字符串 ,F 字符串是开头有一个 f 的字符串文字, Python 会计算其中的用大括号包起来的表达式, 并将计算后的值替换进去.
如果你学过 Ruby,ES6, 你会非常容易接受这样的语法. 另外在速度上, f-strings 是三种方案中最快的:
可以侧面感受到, str.format 最慢,%s 的稍快一点, F-string 是最快的! 你还有什么利用不用它?
现在我写 Python 3.6 以上的代码时, 我已经完全不用另外 2 种格式化用法了.
future-fstrings
通过上面的例子, 希望我们有一个共识, 就是如果你的项目或者工作中使用的 Python 版本已经不小于 3.6,f-string 格式化是首选方式, 不仅在保持功能强大的同时语义上更容易理解, 而且性能也有较大的提升. 但是不巧你用不了 Python 的 f-strings, 还有个选择, 就是 future-fstrings 这个项目. 它的作者也是 pre-commit 作者, 一个 pytest 和 tox 核心开发.
在我个人电脑的 Python 2.7 版本上体验一下:
是不是很酷? 这个库的原理值得大家借鉴, 我详细的分析下.
为什么根本没有 import future_fstrings 代码却能正常运行?
这是因为在你安装 future_fstrings 这个包时, 在 site-packages 下添加一个叫做 aaaaa_future_fstrings.pth 的文件. pth 文件是路径配置文件, 这种文件本来是为了扩充搜索模块路径进 sys.path 的, 也有一些包用它做高级定制.
我们这里提 aaaaa_future_fstrings.pth 在这里被用来导入包了. 所以 CPython 解释器运行时会加载这个 pth 文件, 然后调用其中的 future_fstrings.register 方法.
emmm, pth 文件很多同学感觉很陌生, 其他它离我们很近, 只是作为开发者日常基本不需要关注它. 举一个最常见的例子 easy-install.pth . 有时候为了开发方便, 安装包的时候是这样用的:
这样你使用的 aiomcache, 是你本地的版本:
这样怎么生效的呢? 有些同学会说「嗯, 安装后就放入了 site-packages 下了呗」, 其实不然, 你去系统 Site 包目录下是找不到, 但是呢, sys.path 是可以找到的:
可以看到, 搜索的目录包含了 /Users/dongweiming/aiomcache , 所以能找到. 这是怎么生效的呢? 其实就是靠上面说的 easy-install.pth :
看到了吧, 所以说 pth 配置文件扩充了要搜索模块的路径. 我们测试下把 aiomcache 这样删掉:
再 import, 和查看搜索目录就找不到 aiomcache 了:
这个包实现 f-strings 的原理是?
奥妙就在 # coding: future_fstrings 这一句中, 另外一个写法是 # -*- coding: future_fstrings -*- .
想必大家会想到 Python 2 里面的 # coding: utf-8 头了吧, 这句注释用来声明文件编码. 这个包巧妙的利用了它, 在调用 register 函数时给 codecs 模块注册了新的文件编码方式, 在词法扫描时把 f-strings 转换成 format 的写法, 上面的例子等价于:
不过这样的实现性能肯定比原生的要差很多. 大家有兴趣的可以尝个鲜儿~
结束语
在 Python 之禅中有这么一句:
也就是「应该提供一种, 且最好只提供一种, 一目了然的解决方案」. 虽然 f-strings 不是唯一可能的格式化字符串选择, 但它是最好最正确的那个选择!!!
来源: http://www.tuicool.com/articles/Efyaqqv