簡體   English   中英

Python:為什么if語句比尋址字典要快

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM