[英]Python: Why if-statement is faster than addressing a dictionary
我已經在Stackoverflow中閱讀了幾個線程。 許多人聲稱使用dict比Python中的if-elif-else語句快。 我使用Python 3.7.4進行了一些測試,得出了不同的結果。
我已經建立了一個測試腳本。 我用timeit來衡量我的代碼。 我正在建立一個偽代碼解釋器。 我的解釋器使用if-elif-else語句查找用於解釋特定偽代碼的python過程。 但我想批准dict並進行一些測試。
from timeit import Timer
def add(x, y):
return x + y
def sub(x, y):
return x - y
def mul(x, y):
return x * y
def div(x, y):
return x / y
def foo1(oper, a, b):
return funcs[oper](a, b)
def foo2(oper, a, b):
if oper == 'add':
return a + b
elif oper == 'sub':
return a - b
elif oper == 'mul':
return a * b
else:
return a / b
def foo3(oper, a, b):
subfuncs[oper](a, b)
funcs = {'add': lambda x, y: x + y,
'sub': lambda x, y: x - y,
'mul': lambda x, y: x * y,
'div': lambda x, y: x / y}
subfuncs = {'add': add,
'sub': sub,
'mul': mul,
'div': div}
times_to_run = 10000000
t1 = Timer("foo1('div', 3, 2)", "from __main__ import foo1")
t2 = Timer("foo2('div', 3, 2)", "from __main__ import foo2")
t3 = Timer("foo3('div', 3, 2)", "from __main__ import foo3")
tot1 = t1.timeit(times_to_run)
tot2 = t2.timeit(times_to_run)
tot3 = t3.timeit(times_to_run)
print("Time for foo1 is: {:4.2f}".format(tot1))
print("Time for foo2 is: {:4.2f}".format(tot2))
print("Time for foo3 is: {:4.2f}".format(tot3))
if tot1 > tot2:
res1 = 'slower'
times1 = '{:6.2f}'.format((tot1 / tot2 - 1) * 100)
elif tot1 < tot2:
res1 = 'faster'
times1 = '{:6.2f}'.format((tot2 / tot1 - 1) * 100)
else:
res1 = 'equal'
times1 = ''
print("\nfoo1 is {}% {} in comparison to foo2".format(times1, res1))
if tot2 > tot3:
res2 = 'slower'
times2 = '{:6.2f}'.format((tot2 / tot3 - 1) * 100)
elif tot2 < tot3:
res2 = 'faster'
times2 = '{:6.2f}'.format((tot3 / tot2 - 1) * 100)
else:
res2 = 'equal'
times2 = ''
print("foo2 is {}% {} in comparison to foo3".format(times2, res2))
if tot1 > tot3:
res3 = 'slower'
times3 = '{:6.2f}'.format((tot1 / tot3 - 1) * 100)
elif tot1 < tot3:
res3 = 'faster'
times3 = '{:6.2f}'.format((tot3 / tot1 - 1) * 100)
else:
res3 = 'equal'
times3 = ''
print("foo1 is {}% {} in comparison to foo3".format(times3, res3))
我原以為foo3是最快的函數,而foo2每次都是最快的。 我總是得到與此類似的輸出,並且輸出始終與該輸出一致:
Time for foo1 is: 3.35
Time for foo2 is: 2.99
Time for foo3 is: 3.06
foo1 is 12.18% slower in comparison to foo2
foo2 is 2.51% faster in comparison to foo3
foo1 is 9.44% slower in comparison to foo3
我的問題是,為什么使用if-elif-else語句的foo2比使用使用函數的foo3更快?
PS。 這不是我的實際代碼。 我正在測試哪種方法會更快。
我的問題是,為什么使用if-elif-else語句的foo2比使用使用函數的foo3更快?
好吧,在foo3中,您有一個全局名稱查找(您的函數使用一個全局dict),一個dict查找(=> __getitem__
方法的一個屬性查找+一個對__getitem__
方法調用)和一個函數調用。
在foo2中,由於所有操作都是內聯的,因此您沒有全局查找,沒有dict查找,也根本沒有函數調用,因此,這在很大程度上彌補了按順序丟失測試條件的時間(這是dict查找可以有時更快的原因。而不是分支),特別是當您只有4個條件時...
如果您希望測試相關,則至少應使用函數調用重寫foo2
:
def foo2(oper, a, b):
if oper == 'add':
return add(a, b)
elif oper == 'sub':
return sub(a, b)
elif oper == 'mul':
return mul(a, b)
elif oper == 'div':
return div(a, b)
else:
raise ValueError("unknown operation '{}'".format(oper))
(當然,請確保不要總是使用'add'對其進行測試-但這里的測試通常還可以,因為它使用的是“ div”,這是最后一個條件,因此從理論上講是最壞的情況)。
許多人聲稱使用dict比Python中的if-elif-else語句更快
如果您閱讀像這樣的相關問題(和答案),您會發現它確實不僅取決於分支與字典查找(多少個分支/字典鍵,您的代碼在做什么等)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.