Python 3.6中的f-strings

时间:2017-03-30 16:25:20

标签: python python-3.x python-3.6 f-string

我真的很想深入研究代码风格,从现在开始知道是否最好使用新风格会很有趣。

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

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

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

我理解它的基础是:

  

简单比复杂更好。

然而,性能问题如何,它们之间是否存在差异?或者它只是一个相同功能的简单外观?

5 个答案:

答案 0 :(得分:34)

  

我担心在下一个Python版本中它会被弃用

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

  

本PEP不建议删除或弃用任何现有的字符串格式化机制。

引入格式化字符串以解决格式化字符串的其他方法的一些缺点;不要抛弃旧方法并强迫上帝 - 如果他们希望他们的代码适用于Python 3.6 +,那么知道有多少项目要使用f-string。

至于这些的表现,似乎我最初怀疑他们可能会更慢是错误的,f-strings似乎很容易超越他们的.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更好。

答案 1 :(得分:23)

基于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在没有属性或函数调用的情况下处理格式化,这会强加类型检查和内存开销。根据{{​​1}},这导致大约3倍的性能提升(对于我的特定功能)

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

答案 2 :(得分:9)

有一件事未提及(这使旧技术不可用)是插值仅用于字符串文字。意思是,字符串在运行时呈现一次。模板不能再次使用更新的变量,例如:

str_template.format(args)

另一种情况是i18n,其中使用了string.Template。没有较旧的技术,许多用例是不可能的。享受字符串插值,但不要在不合适的地方使用它,即需要可重用模板的位置。

答案 3 :(得分:1)

如果您想继续支持python 3.5,可以使用fstring

pip install fstring

from fstring import fstring

x = 1

y = 2.0

plus_result = "3.0"

print fstring("{x}+{y}={plus_result}")

# Prints: 1+2.0=3.0

答案 4 :(得分:0)

我怀疑 str.format() 会被弃用,因为这对现有项目来说是一场噩梦。话虽这么说...

string = f'This is a {object}'

更容易阅读
string = 'This is a {}'.format(object)

所以我说尽可能使用 f-strings。