Python字符串格式化:'%'比'format'函数更高效吗?
Python字符串格式化:'%'比'format'函数更高效吗?
我想要比较使用不同变量在Python中构建字符串的方法:
- 使用
+
进行拼接(称为“加号”) - 使用
%
- 使用
"".join(list)
- 使用
format
函数 - 使用
"{0.
}".format(object)
我比较了3种类型的场景:
- 包含2个变量的字符串
- 包含4个变量的字符串
- 包含4个变量的字符串,每个变量使用两次
我对每种方法进行了100万次操作的测量,并对6次测量进行了平均。我得出了以下结果:
test_plus: 0.29480
test_percent: 0.47540
test_join: 0.56240
test_format: 0.72760
test_formatC: 0.90000
test_plus_long: 0.50520
test_percent_long: 0.58660
test_join_long: 0.64540
test_format_long: 1.03400
test_formatC_long: 1.28020
test_plus_long2: 0.95220
test_percent_long2: 0.81580
test_join_long2: 0.88400
test_format_long2: 1.51500
test_formatC_long2: 1.97160
在每种场景下,我得出了以下结论:
- 拼接似乎是最快的方法之一
- 使用
%
进行格式化比使用format
函数要快得多
我认为format
比%
要好得多(例如在这个问题中),而%
几乎已经被弃用了。
因此,我有几个问题:
%
真的比format
更快吗?- 如果是这样,为什么会这样?
"{} {}".format(var1, var2)
比"{0.attribute1} {0.attribute2}".format(object)
更高效的原因是什么?
为了参考,我使用以下代码来测量不同的时间。
import time def timing(f, n, show, *args): if show: print f.__name__ + ":\t", r = range(n/10) t1 = time.clock() for i in r: f(*args); f(*args); f(*args); f(*args); f(*args); f(*args); f(*args); f(*args); f(*args); f(*args) t2 = time.clock() timing = round(t2-t1, 3) if show: print timing return timing class values(object): def __init__(self, a, b, c="", d=""): self.a = a self.b = b self.c = c self.d = d def test_plus(a, b): return a + "-" + b def test_percent(a, b): return "%s-%s" % (a, b) def test_join(a, b): return ''.join([a, '-', b]) def test_format(a, b): return "{}-{}".format(a, b) def test_formatC(val): return "{0.a}-{0.b}".format(val) def test_plus_long(a, b, c, d): return a + "-" + b + "-" + c + "-" + d def test_percent_long(a, b, c, d): return "%s-%s-%s-%s" % (a, b, c, d) def test_join_long(a, b, c, d): return ''.join([a, '-', b, '-', c, '-', d]) def test_format_long(a, b, c, d): return "{0}-{1}-{2}-{3}".format(a, b, c, d) def test_formatC_long(val): return "{0.a}-{0.b}-{0.c}-{0.d}".format(val) def test_plus_long2(a, b, c, d): return a + "-" + b + "-" + c + "-" + d + "-" + a + "-" + b + "-" + c + "-" + d def test_percent_long2(a, b, c, d): return "%s-%s-%s-%s-%s-%s-%s-%s" % (a, b, c, d, a, b, c, d) def test_join_long2(a, b, c, d): return ''.join([a, '-', b, '-', c, '-', d, '-', a, '-', b, '-', c, '-', d]) def test_format_long2(a, b, c, d): return "{0}-{1}-{2}-{3}-{0}-{1}-{2}-{3}".format(a, b, c, d) def test_formatC_long2(val): return "{0.a}-{0.b}-{0.c}-{0.d}-{0.a}-{0.b}-{0.c}-{0.d}".format(val) def test_plus_superlong(lst): string = "" for i in lst: string += str(i) return string def test_join_superlong(lst): return "".join([str(i) for i in lst]) def mean(numbers): return float(sum(numbers)) / max(len(numbers), 1) nb_times = int(1e6) n = xrange(5) lst_numbers = xrange(1000) from collections import defaultdict metrics = defaultdict(list) list_functions = [ test_plus, test_percent, test_join, test_format, test_formatC, test_plus_long, test_percent_long, test_join_long, test_format_long, test_formatC_long, test_plus_long2, test_percent_long2, test_join_long2, test_format_long2, test_formatC_long2, # test_plus_superlong, test_join_superlong, ] val = values("123", "456", "789", "0ab") for i in n: for f in list_functions: print ".", name = f.__name__ if "formatC" in name: t = timing(f, nb_times, False, val) elif '_long' in name: t = timing(f, nb_times, False, "123", "456", "789", "0ab") elif '_superlong' in name: t = timing(f, nb_times, False, lst_numbers) else: t = timing(f, nb_times, False, "123", "456") metrics[name].append(t) # Get Average print "\n===AVERAGE OF TIMINGS===" for f in list_functions: name = f.__name__ timings = metrics[name] print "{:>20}:\t{:0.5f}".format(name, mean(timings))