Python中最快的格式化字符串方式

在Python中格式化字符串的方式有很多种。

%占位符

第一种是传承自C语言printf函数的使用%占位符格式化字符串,如'%d' % 100,这种方式严格来说是使用%作为算数运算符进行的二元运算,而且有一个限制是只能进行数字和字符串的格式化输出。

str.format()

第二种是str.format()方法,用法如'{}'.format(1),等价于str.format('{}',1)

str.format()可以格式化实现了__str__()魔法方法的所有类型,如列表'{}'.format([1,2,3])和字典'{}'.format({'a':1, 'b':2})

str.format()在格式化多个对象的时候可以自由调整对象位置或者一个对象在字符串中出现多次,如'{1}{0}{1}'.format('a','b'),得到'bab'

str.format()还可以进行键值传递,如'{name} is {age} years ago.'.format(name = 'Mike', age= 18)

f-string模板字符串

f-string模板字符串是Python3.6之后版本的新特性,类似于str.format()方法,但是简洁了很多,在字符串前加f标记后可以直接直接解析大括号里的表达式,并且内部的实现方法也有不同,比str.format()方法快很多。

>>>name = 'Mike'
>>>age = 18
>>>f'{name} is {age + 1} years old.'
'Mike is 19 years old.'

三种方式的效率比较

我们可以用Jupyter Notebook中%timeit标记来测试这三种字符串格式化方法的效率。

%timeit '%d' %1
154 ns ± 3 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit '%s' %'a'
55.2 ns ± 0.223 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit '{}'.format(1)
261 ns ± 5.67 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit '{}'.format('a')
160 ns ± 7.32 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit '{}'.format(1,2,3)
836 ns ± 29.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit f'{1}'
11.7 ns ± 0.0736 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
%timeit f'{"a"}'
11.7 ns ± 0.25 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
%timeit f'{1,2,3}'
12.2 ns ± 0.882 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

可以看到f-string最快,%占位符次之,而str.format()方法是最慢的。我们可以通过分析字节码来看一下这三种方法的内部实现。

from dis import dis
dis(lambda: '%d' % 1)
  1           0 LOAD_CONST               1 ('%d')

              2 LOAD_CONST               2 (1)

              4 BINARY_MODULO

              6 RETURN_VALUE
dis(lambda: '{}'.format(1))
  1           0 LOAD_CONST               1 ('{}')

              2 LOAD_ATTR                0 (format)

              4 LOAD_CONST               2 (1)

              6 CALL_FUNCTION            1

              8 RETURN_VALUE
dis(lambda: f'{1}')
  1           0 LOAD_CONST               1 (1)

              2 FORMAT_VALUE             0

              4 RETURN_VALUE

我们可以看到正如上文说到的%占位符事实上是一个二元运算符的算术运算,而str.format()方法进行了函数调用,f-string则是新的Python字节码指令,也在底层进行了优化,所以f-string更快也是很显然的。

f-string在代码的简洁性和直观性上都很突出,并且有着明显的效率上的优势,希望这一方法成为大家平时编码过程中的首选,当然潜在意思就是希望大家尽快迁移到Python3.6及以上的版本了。

最后给大家介绍一下f-string的一些数字的格式化方法。

f-string格式化数字

转换进制

f'{20:b} {20:o} {26:x} {26:X}'
'10100 24 1a 1A'

保留小数位数

f'{10:.3f}'
'10.000'

规定宽度,前导'0'’

f'{123:05}'
'00123'

规定宽度,前导空格

f'{123:5}'
'  123'

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏恰同学骚年

数据结构基础温故-2.栈

现实生活中的事情往往都能总结归纳成一定的数据结构,例如餐馆中餐盘的堆叠和使用,羽毛球筒里装的羽毛球等都是典型的栈结构。而在.NET中,值类型在线程栈上进行分配,...

813
来自专栏Android研究院

深入理解链表和手写链表以及面试中常问链表的问题

上一期 讲到了 顺序表与链表的基本知识 了解链表的基本知识。并且分析了ArrayList的源码。顺序表(随机访问速度快,插入和删除效率低)和链表(随机访问速度慢...

9542
来自专栏python全栈布道师

2017年8月28日技术日记

4116
来自专栏格子的个人博客

Java源码阅读之LinkedList - JDK1.8

前文基于缓冲数组的ArrayList已经分析过,那么同样作为List实现的LinkedList又有什么不一样呢?

992
来自专栏androidBlog

笔试题—字符串常见的算法题集锦

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

1311
来自专栏LanceToBigData

Java集合源码分析(二)Linkedlist

前言   前面一篇我们分析了ArrayList的源码,这一篇分享的是LinkedList。我们都知道它的底层是由链表实现的,所以我们要明白什么是链表? 一、Li...

2747
来自专栏Golang语言社区

【Go 语言社区】POJ 1047 Round and Round We Go 循环数新解

题目描述: 给定一字符串表示的高精度数,判断它是否是可循环的。如果假设字符串num的长为n,则将num从1开始乘到n,如果每次得到的结果包含的字符元素都和a是相...

35511
来自专栏尾尾部落

[剑指offer] 数字在排序数组中出现的次数

正常的思路就是二分查找了,我们用递归的方法实现了查找k第一次出现的下标,用循环的方法实现了查找k最后一次出现的下标。 除此之外,还有另一种奇妙的思路,因为da...

641
来自专栏书山有路勤为径

合法的出栈序列

poj 1363 Rails 已知从1至n的数字序列,按顺序入栈,每个数字入栈后即可出栈,也可在栈中 停留,等待后面的数字入栈出栈后,该数字再出栈,求该数字序...

812
来自专栏从流域到海域

《数据结构》 定长顺序串常用操作代码集合

代码来自老师上课使用的ppt或者课本 /*定长顺序串*/ #define MAXLEN 40 typedef struct { char ch[M...

1956

扫码关注云+社区

领取腾讯云代金券