切换/案例使用,如何有效地使用if-elif-else功能?

时间:2018-01-03 10:47:09

标签: python python-3.x performance switch-statement processing-efficiency

我正在尝试为各种情况构建一个检查一个值的有效方案,每个情况表示需要执行的不同函数。 具体来说,我有一个带有功能按钮的键盘矩阵,它们都应该提供不同的功能,但是代码应该在有效的情况下执行,因此在得出结论之前不要浪费太多时间检查每个语句。

这是我想要做的一个例子,但由于lambda用法/ lambda创建,它似乎仍然效率低下:

def data(value):
    global combination
    functions = {
                'A' : print('Arm'),
                'B' : pass,
                'C' : lambda x: return False,
                'D' : print('Disarm'),
                '*' : lambda x: return x, #Asterisk=Enter
                '#' : lambda x: x='', #Hashtag=InputCorrection
                }(combination)
    if type(value) is int:
        ##Collect numbers, irrelevant##
        pass
    if type(value) is str:
        ##Function Buttons##
        return functions.get(value, 'Default = Ignore Input')

据我所知,这个 if-elif-else 场景的最快方法是字典,但如果我错了,请纠正我。 我正在寻找比lambda x:更有效的方法,因为我已经读过这些lambda函数是在data(value)函数的每次调用时生成的,因此消耗时间。

我需要一个节省时间的程序,因为它不应该减慢在键盘上检测“按下按钮”的过程。

另请注意:不可能有不正确的值,因此没有任何失败。在提供的函数被调用之前,将会选择 Fall-throughs ,但一般来说,在这种情况下,它们不存在

2 个答案:

答案 0 :(得分:4)

  

据我所知,这个if-elif-else场景的最快方法是字典

不要假设,基准。 timeit模块是您的朋友。

  

我正在寻找一种比lambda x:更有效的方法,因为我已经读过这些lambda函数是在每次调用data(value)函数时生成的,因此消耗时间

这是事实,但在全局命名空间中查找名称也需要时间。

还要注意问题不在于lambdas本身,内部函数会表现出相同的问题 - 而当我们处理它时,如果你的lambdas只是调用另一个函数(即你有{"A": lambda x: funcA(x)}),你甚至不需要lambda,只需使用{"A": funcA, "B": funcB, },你不仅会保存lambda instanciation时间,而且还会保存(并且更重要的)一个函数调用,包含所有的堆栈操作。

所以再一次,不要假设,基准。

实际上,在您甚至担心基准测试之前,请检查是否确实是性能问题,然后进行配置以找出瓶颈在哪里。我们人类通常很难猜测这类事情,而且我不止一次看到开发人员浪费时间“优化”代码的错误部分 - 使其难以理解且无法实现 - 在不使用任何有意义的性能改进的情况下使用探查器你可以找到一些“快速获胜”,花了一天的时间来实现,对可读性没有影响,并且显着改善了性能(有时提高了一个数量级)。

回到你的用例 - 你主要有3个可能的实现,一个普通的if / elif /,一个本地字典和一个全局字典。您可以使用timeit对每个解决方案进行模拟实现并对其进行基准测试,然后您就会知道哪个是最快的python版本。如果您计划支持不同的Python版本,请确保重复所有版本的测试。

答案 1 :(得分:0)

我已经更新了代码,并提出了一个可行的解决方案,仅供将来参考。 这个目前有效,我稍后会做一些基准测试,然后再回过头来看看它是否是性能最佳的方法。

更新,基准: 好吧,我对代码进行了基准测试,使用的代码和输出如下。 我需要检查一下我是如何正确编码的,所以我有一个可读的格式的多次运行和比较时间,不得不手动调整它。 但如上所述,在这种情况下,性能时间确实不是一个大问题。

  

通过函数,全局变量

import timeit
import logging

global combination,functions
combination = ''

MATRIX = [ [1,2,3,'A'],
           [4,5,6,'B'],
           [7,8,9,'C'],
           ['*',0,'#','D'] ]

## KEYPAD FUNCTIONS ##
def A():
    print ('Arm')
def B():
    print ('Function B')
def C():
    global combination
    print ('Cancel')
    combination = None 
def D():
    print ('Disarm')
def asterisk():
    print ('Enter')
def hashtag():  
    print ('Input Correction')
    global combination
    combination = ''

## DICTIONARY FOR FUNCTION ACCESS ##
functions = {
                'A' : A, #Do Function A
                'B' : B, #Do Function B
                'C' : C, #Do Function C
                'D' : D, #Do Function D
                '*' : asterisk, #Asterisk=Enter
                '#' : hashtag #Hashtag=InputCorrection
                }

## DATA EVALUATION FROM BUTTONS ##
def data(value):
    global combination
    if isinstance(value, int):
        #Collect numbers#
        combination += str(value)
        return False
    if isinstance(value, str):
        #Function Buttons#
        return functions[value]()

## MAIN ##
print('Starting...')
try:
    print('Execution time [#Numbers#]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[0][0]', number=1, globals=globals()))
#    print('Execution time [2]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[0][1]', number=1, globals=globals()))
#    print('Execution time [3]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[0][2]', number=1, globals=globals()))
#    print('Execution time [4]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[1][0]', number=1, globals=globals()))
#    print('Execution time [5]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[1][1]', number=1, globals=globals()))
#    print('Execution time [6]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[1][2]', number=1, globals=globals()))
#    print('Execution time [7]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[2][0]', number=1, globals=globals()))
#    print('Execution time [8]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[2][1]', number=1, globals=globals()))
#    print('Execution time [9]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[2][2]', number=1, globals=globals()))
#    print('Execution time [0]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[3][1]', number=1, globals=globals()))
    print('Execution time [A]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[0][3]', number=1, globals=globals()))
    print('Execution time [B]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[1][3]', number=1, globals=globals()))
    print('Execution time [C]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[2][3]', number=1, globals=globals()))
    print('Execution time [D]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[3][3]', number=1, globals=globals()))
    print('Execution time [*]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[3][0]', number=1, globals=globals()))
    print('Execution time [#]:',timeit.timeit(stmt='data(checker)', setup='checker=MATRIX[3][2]', number=1, globals=globals()))
except:
    logging.exception('Exception:')
print('Done.')
  

与if-elif的区别,仍然是全局变量

## DATA EVALUATION FROM BUTTONS ##
def data(value):
    global combination
    if isinstance(value, int):
        combination += str(value)
    if isinstance(value, str):
        if value == 'A':
            print ('Arm')
        elif value == 'B':
            print ('Function B')
        if value == 'C':
            print ('Cancel')
            combination = None
        elif value == 'D':
            print ('Disarm')
        if value == '*':
            print ('Enter')
        elif value == '#':
            combination = ''
  

包含函数,局部变量

## DICTIONARY FOR FUNCTION ACCESS ##
functions = {
                'A' : A, #Do Function A
                'B' : B, #Do Function B
                'C' : C, #Do Function C
                'D' : D, #Do Function D
                '*' : asterisk, #Asterisk=Enter
                '#' : hashtag #Hashtag=InputCorrection
                }

## DATA EVALUATION FROM BUTTONS ##
def data(value):
    combination = ''
    if isinstance(value, int):
        #Collect numbers#
        combination += str(value)
        return False
    if isinstance(value, str):
        #Function Buttons#
        return functions[value]()
  

输出,手动编辑以提高可读性

debug_timing_ver1 - with functions, global
    Starting...
    Execution time [#Numbers#]: 0.0000276039991149446
    Arm
    Execution time [A]:         0.0010460909998073475
    Function B
    Execution time [B]:         0.0007861440008127829
    Cancel
    Execution time [C]:         0.0007383310003206134
    Disarm
    Execution time [D]:         0.0005742169996665325
    Enter
    Execution time [*]:         0.0007173410012910608
    Input Correction
    Execution time [#]:         0.0006719249995512655
    Done.
debug_timing_ver2 - if-elif
    Starting...
    Execution time [#Numbers#]: 0.000028021000616718084
    Arm
    Execution time [A]:         0.0007630699983565137
    Function B
    Execution time [B]:         0.000840361999507877
    Cancel
    Execution time [C]:         0.001447234999432112
    Disarm
    Execution time [D]:         0.0002588010011095321
    Enter
    Execution time [*]:         0.0008585909999965224
    Execution time [#]:         0.000026667001293390058
    Done.
debug_timing_ver3 - with functions, local
    Starting...
    Execution time [#Numbers#]: 0.00002343800042581279
    Arm
    Execution time [A]:         0.0012339030017756158
    Function B
    Execution time [B]:         0.0009442159989703214
    Cancel
    Execution time [C]:         0.00036010300027555786
    Disarm
    Execution time [D]:         0.0002615100002003601
    Enter
    Execution time [*]:         0.0007838519995857496
    Input Correction
    Execution time [#]:         0.0002430200001981575
    Done.