2016-08-02 51 views
6

我看到使用的格式字符串类似这样的很多人:格式字符串VS串联

root = "sample" 
output = "output" 
path = "{}/{}".format(root, output) 

而不是简单地连接字符串是这样的:

path = root + '/' + output 

进行格式字符串有更好的性能,或者这只是为容貌?

+0

我猜他们的表现更糟。但是我仍然更喜欢非性能关键位置的格式字符串。 – doublep

+2

[Python string formatting:%vs concatenation]可能重复(http://stackoverflow.com/questions/34619384/python-string-formatting-vs-concatenation) –

回答

8

这只是为了看起来。一眼就能看到格式是什么。我们中的许多人喜欢可读性比微优化更好。

让我们来看看IPython中的%timeit说:

In [1]: %timeit root = "sample"; output = "output"; path = "{}/{}".format(root, output) 
The slowest run took 33.07 times longer than the fastest. This could mean that an intermediate result is being cached. 
1000000 loops, best of 3: 209 ns per loop 

In [2]: %timeit root = "sample"; output = "output"; path = root + '/' + output 
The slowest run took 19.63 times longer than the fastest. This could mean that an intermediate result is being cached. 
10000000 loops, best of 3: 97.2 ns per loop 

In [3]: %timeit root = "sample"; output = "output"; path = "%s/%s" % (root, output) 
The slowest run took 19.28 times longer than the fastest. This could mean that an intermediate result is being cached. 
1000000 loops, best of 3: 148 ns per loop 
+1

请注意,自Python 3.6以来,您可以使用path =“{根}/{输出}“,这是非常简单的... – comte

6

与大多数事情一样,会有一个性能上的差异,但问自己“是否真的重要,如果这是NS快?”。 root + '/' output方法快速且简单。但是这样做会很难看,当你有多个变量来打印

foo = "X = " + myX + " | Y = " + someY + " Z = " + Z.toString() 

VS

foo = "X = {} | Y= {} | Z = {}".format(myX, someY, Z.toString()) 

哪个更容易了解正在发生的事情真正的快?除非你确实需要剔除性能,选择最容易让人阅读和理解的方式

4

字符串格式在绑定数据时没有数据类型。在连接时,我们必须相应地键入强制转换或转换数据。

例如:

a = 10 
b = "foo" 
c = str(a) + " " + b 
print c 
> 10 foo 

它可以通过字符串格式化完成此操作:

a = 10 
b = "foo" 
c = "{} {}".format(a, b) 
print c 
> 10 foo 

这样:在占位符{} {},我们假设两件事情会进一步即,在这种情况下, ,分别是ab

1

这是看起来和代码的维护。如果使用格式,编辑代码会更容易。另外,当你使用+时,你可能会错过空间等细节。为你和可能的维护者使用格式。

2

这不仅仅是为了“看起来”,或为强大的词法类型转换;这也是国际化的必要条件。

根据选择的语言,您可以换出格式字符串。

在源代码中插入一长串字符串连接,这实际上无法正确执行。

2

我同意格式化主要用于可读性,但自从3.6版本中发布f-字符串以来,表格在性能方面出现了变化。我还认为f字符串更易读/可维护,因为1)它们可以像大多数常规文本一样左右读取,2)由于变量在字符串中,所以避免了串联的间距相关缺点。

运行此代码:

from timeit import timeit 

runs = 1000000 


def print_results(time, start_string): 
    print(f'{start_string}\n' 
      f'Total: {time:.4f}s\n' 
      f'Avg: {(time/runs)*1000000000:.4f}ns\n') 


t1 = timeit('"%s, %s" % (greeting, loc)', 
      setup='greeting="hello";loc="world"', 
      number=runs) 
t2 = timeit('f"{greeting}, {loc}"', 
      setup='greeting="hello";loc="world"', 
      number=runs) 
t3 = timeit('greeting + ", " + loc', 
      setup='greeting="hello";loc="world"', 
      number=runs) 
t4 = timeit('"{}, {}".format(greeting, loc)', 
      setup='greeting="hello";loc="world"', 
      number=runs) 

print_results(t1, '% replacement') 
print_results(t2, 'f strings') 
print_results(t3, 'concatenation') 
print_results(t4, '.format method') 

得到我的机器上这样的结果:

% replacement 
Total: 0.3044s 
Avg: 304.3638ns 

f strings 
Total: 0.0991s 
Avg: 99.0777ns 

concatenation 
Total: 0.1252s 
Avg: 125.2442ns 

.format method 
Total: 0.3483s 
Avg: 348.2690ns 

类似的回答不同的问题上给出this answer