Python - 'elif: return()'语句太多了?

5
我有一个函数,需要传递两个参数:
def function(a, b):
    if   a == 'd' : return(4*b)
    elif a == '!' : return(5)
    elif a == 'k' : return(1-2*k+k**2)
    elif a == 'Z' : return(1/k)
    (...)

a正在检查它是否等于单个字符,而b始终是一个数字;该函数也总是返回一个数字。但有时它的返回值并不总是简单的。

def function(a, b):
    (...)
    elif a == '2':
        temp_b = foo(b)
        if b == 2 : temp_b += 2
        return(temp_b)

我有一长串elif语句,有没有更好的方法来处理这个问题?


1
是的,把它变成多个函数。看起来你只是用它来做一切:def all_funcs(operation, operand)不符合Pythonic风格。 - TemporalWolf
2个回答

10

实际上是的。首先,Python没有象征性的switch语句, 当语句变得足够长时,它提供了二进制搜索,比线性搜索快得多。

在Python中,您可以使用字典,无论是具有精确值还是自定义函数:

def other_case(x):
    '''We can store non-lambdas too'''

    return 8

functions = {
    'd': lambda x: 4*x,
    '!': lambda x: 5,
    'k': lambda x: (1-2*x+x**2),
    'Z': lambda x: (1/x),
    '*': other_case,
}

只需编写一个简短的包装器即可调用此函数:

def call(a, x):
    return functions[a](x)

这个操作的时间复杂度为 O(1),或者说是常量级别的,因此不仅更易读,而且速度也更快。

编辑

如果你有一定范围内的数字,可以遍布整个范围,那么你还可以使用列表和变换。比如说我要处理从 2000 Da 到 5000 Da(我是一名生物学家),每隔 100 Da 进行一次处理,但编码一个包含 500 个项目的列表毫无意义,但是我可以使用一个包含 30 个项目的列表来考虑整个范围。

from __future__ import division         # for //, floor division

def mass2000(x):
    '''Do something for mass of 2000'''

    return 1/x

def mass2100(x):
    '''Do something for mass of 2100'''

    return x

def mass2200(x):
    '''Do something for mass of 2200'''

    return x**2


lookup = [
    mass2000,
    mass2100,
    mass2200,
    # ....
]


def call(mass, x):
    if (mass < 2000 or mass > 5000):
        raise ValueError("Mass out of range")

    return lookup[(mass - 2000) // 100](x)

1
我认为函数字典可能是一种可行的方式。直到现在,我还不知道如何以这种方式实现它! - Graviton
假设 a 是不同的类型。如果是整数,你可以使用列表而不是字典。那么如果 a 是浮点数呢? - saintsfan342000
1
@saintsfan342000 实际上你可以使用地板除法。我以前实际上曾经不得不这样做过。我会编辑我的回答。 - Alex Huszagh

1

将所有情况分为单独的迷你函数或lambda函数可能是有益的,然后使用字典,键为字符,值为相应的函数/lambda函数。

下面是一个例子:

def function_2(b):
    temp_b = foo(b)
    if b == 2 : temp_b += 2
    return(temp_b)

fp = {
    2 : function_2
}

然后你可以编写一个循环遍历该字典,并进行键的匹配,一旦匹配成功,你就可以像这样传递b。

for element in fp:
    if element == a:
        fp[element](b)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接