Python 3.6中的f-strings

2024-04-25 22:19:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我真的很喜欢深入研究代码风格,很有意思的是知道从现在开始,在所有情况下,使用新的风格是否更好。

我在Python 3.5项目中使用了很多.format(),我担心在下一个Python版本中会因为这种新的字符串文本而被弃用。

>>> name = "Test"
>>> f"My app name is {name}."
'My app name is Test.'

格式化字符串功能是否完全取代了原来的format()

我的理解是基于这样的想法:

Simple is better than complex.

但是,性能问题呢?它们之间有什么区别吗?还是只是同一功能的简单外观?


Tags: 项目字符串代码nametest文本功能版本
3条回答

I'm afraid that it will be deprecated during the next Python versions

别这样,str.format不会出现(也没有理由)很快就要离开,引入f前缀字符串的PEP甚至states in its Abstract

This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms.

引入格式化字符串是为了解决其他格式化字符串的方法所存在的一些缺点;不要抛弃旧的方法,强迫上帝知道如果他们希望自己的代码在Python3.6+上运行,有多少项目可以使用f-string。


至于这些字符串的性能,我最初的怀疑似乎是错误的,f字符串似乎很容易胜过它们的.format对应字符串:

➜ cpython git:(master) ./python -m timeit -s "a = 'test'" "f'formatting a string {a}'"
500000 loops, best of 5: 628 nsec per loop
➜ cpython git:(master) ./python -m timeit "'formatting a string {a}'.format(a='test')"
100000 loops, best of 5: 2.03 usec per loop

这些都是在撰写本文时针对CPython存储库的主分支完成的;它们肯定会发生更改:

  • f-strings,作为一个新特性,可能有可能的优化
  • 对CPython的优化可能会使.format更快(例如Speedup method calls 1.2x

但实际上,不要太担心速度,要担心什么对你和其他人来说更可读。

在许多情况下,这将是f-strings,但是there's some cases其中format更好。

有一件事没有提到,这使得对旧技术的反对成为可能,那就是插值只针对字符串文本。也就是说,字符串在运行时呈现一次。模板不能与更新的变量一起再次使用。如你所愿:

str_template.format(args)

另一个例子是i18n,其中使用string.Template。如果没有旧的技术,许多用例是不可能的。享受字符串插值,但它不是每个用例都可以使用的,也就是需要可重用模板的地方。

为了构建Jim的答案并解决性能问题,我使用python的dis模块来比较两个语法不同但功能相同的函数的字节码指令。

import dis

def f1():
    a = "test"
    return f"{a}"

def f2():
    return "{a}".format(a='test')

print(dis.dis(f1))
print(dis.dis(f2))

其结果是:

 11           0 LOAD_CONST               1 ('test')
              2 STORE_FAST               0 (a)

 12           4 LOAD_FAST                0 (a)
              6 FORMAT_VALUE             0
              8 RETURN_VALUE
None
 15           0 LOAD_CONST               1 ('{a}')
              2 LOAD_ATTR                0 (format)
              4 LOAD_CONST               2 ('test')
              6 LOAD_CONST               3 (('a',))
              8 CALL_FUNCTION_KW         1
             10 RETURN_VALUE
None

可以看到,f-string处理格式时没有属性或函数调用,这会增加类型检查和内存开销。根据timeit,这将导致大约3倍的性能提高(对于我的特定功能)

>>> timeit.timeit('f1()', 'from __main__ import f1', number=100000)
0.012325852433775708
>>> timeit.timeit('f2()', 'from __main__ import f2', number=100000)
0.036395029920726074

相关问题 更多 >