Chciałem porównać różne zbudować ciąg w Pythonie od różnych zmiennych:Formatowanie ciągów w języku Python: czy '%' jest bardziej wydajne niż funkcja 'formatowania'?
- użyciu
+
aby złączyć (dalej 'plus') - wykorzystaniem
%
- wykorzystaniem
"".join(list)
- użyciu
format
funkcja - przy użyciu
"{0.<attribute>}".format(object)
I w porównaniu z 3 rodzajów scenari
- łańcuchowych 2 zmiennych
- łańcuch z 4 zmiennych
- łańcuch z 4 zmienne, każdy dwukrotnego
że mierzy 1 milion działania każdego czasu i wykonał średnio ponad 6 pomiarów. Wpadłem na następujących taktowania:
W każdym scenariuszu, wpadłem następującego wniosku
- Powiązanie wydaje się być jednym z najszybszych metod
- Formatowanie przy użyciu
%
jest znacznie szybszy niż formatowanie z funkcjąformat
Wierzę, że format
jest znacznie lepszy niż %
(np. w this question) i %
był prawie przestarzały.
Mam więc kilka pytań:
- Is
%
naprawdę szybciej niżformat
? - Jeśli tak, dlaczego tak jest?
- Dlaczego numer
"{} {}".format(var1, var2)
jest bardziej wydajny niż"{0.attribute1} {0.attribute2}".format(object)
?
Dla porównania, że stosuje się następujący kod mierzyć różne czasy.
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
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))
Użyj 'timeit' zamiast swojej własnej funkcji, może się zdarzyć, że pierwsze wykonanie będzie wolne, ale wykonanie następnej funkcji będzie szybsze, ale w rzeczywistości funkcja będzie wywoływana tylko raz. https://docs.python.org/2/library/timeit.html –
Jak wspomniano w @MaximilianPeters, powinieneś używać 'timeit' do uzyskiwania godnych zaufania wyników. –
Dzięki chłopaki. Sprawdziłem 'timeit', ale powinienem być na wysokim poziomie tego dnia, ponieważ wierzyłem, że jest obsługiwane tylko w Pythonie 3.x i używam głównie wersji 2.7. –