我想用Python编写一个函数,根据输入索引的值返回不同的固定值。

在其他语言中,我会使用switch或case语句,但Python似乎没有switch语句。在此场景中,推荐的Python解决方案是什么?


当前回答

class Switch:
    def __init__(self, value):
        self.value = value

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        return False # Allows a traceback to occur

    def __call__(self, *values):
        return self.value in values


from datetime import datetime

with Switch(datetime.today().weekday()) as case:
    if case(0):
        # Basic usage of switch
        print("I hate mondays so much.")
        # Note there is no break needed here
    elif case(1,2):
        # This switch also supports multiple conditions (in one line)
        print("When is the weekend going to be here?")
    elif case(3,4):
        print("The weekend is near.")
    else:
        # Default would occur here
        print("Let's go have fun!") # Didn't use case for example purposes

其他回答

class switch(object):
    value = None
    def __new__(class_, value):
        class_.value = value
        return True

def case(*args):
    return any((arg == switch.value for arg in args))

用法:

while switch(n):
    if case(0):
        print "You typed zero."
        break
    if case(1, 4, 9):
        print "n is a perfect square."
        break
    if case(2):
        print "n is an even number."
    if case(2, 3, 5, 7):
        print "n is a prime number."
        break
    if case(6, 8):
        print "n is an even number."
        break
    print "Only single-digit numbers are allowed."
    break

测验:

n = 2
#Result:
#n is an even number.
#n is a prime number.
n = 11
#Result:
#Only single-digit numbers are allowed.

还有另一种选择:

def fnc_MonthSwitch(int_Month): #### Define a function take in the month variable 
    str_Return ="Not Found"     #### Set Default Value 
    if int_Month==1:       str_Return = "Jan"   
    if int_Month==2:       str_Return = "Feb"   
    if int_Month==3:       str_Return = "Mar"   
    return str_Return;          #### Return the month found  
print ("Month Test 3:  " + fnc_MonthSwitch( 3) )
print ("Month Test 14: " + fnc_MonthSwitch(14) )

Python 3.10(2021)引入了match-case语句,该语句提供了Pythons“switch”的一流实现。例如:

def f(x):
    match x:
        case 'a':
            return 1
        case 'b':
            return 2
        case _:
            return 0   # 0 is the default case if x is not found

match-case语句比这个简单的示例强大得多。


以下原始答案写于2008年,当时还未提供匹配案例:

你可以用字典:

def f(x):
    return {
        'a': 1,
        'b': 2,
    }[x]

扩展“dict as switch”思想。如果要为交换机使用默认值:

def f(x):
    try:
        return {
            'a': 1,
            'b': 2,
        }[x]
    except KeyError:
        return 'default'

与abarnert的回答类似,这里有一个专门针对以下用例的解决方案:为开关中的每个“case”调用单个函数,同时避免lambda或partial,以实现超简洁,同时仍然能够处理关键字参数:

class switch(object):
    NO_DEFAULT = object()

    def __init__(self, value, default=NO_DEFAULT):
        self._value = value
        self._result = default

    def __call__(self, option, func, *args, **kwargs):
        if self._value == option:
            self._result = func(*args, **kwargs)
        return self

    def pick(self):
        if self._result is switch.NO_DEFAULT:
            raise ValueError(self._value)

        return self._result

示例用法:

def add(a, b):
    return a + b

def double(x):
    return 2 * x

def foo(**kwargs):
    return kwargs

result = (
    switch(3)
    (1, add, 7, 9)
    (2, double, 5)
    (3, foo, bar=0, spam=8)
    (4, lambda: double(1 / 0))  # if evaluating arguments is not safe
).pick()

print(result)

请注意,这是链接调用,即switch(3)(…)(。将所有内容放在一个表达式中也很重要,这就是为什么我在隐式行延续的主调用周围使用了额外的括号。

如果您打开未处理的值,例如开关(5)(1,…)(2,…)。。。返回-1。