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

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


当前回答

我发现一种常见的交换机结构:

switch ...parameter...
case p1: v1; break;
case p2: v2; break;
default: v3;

可以用Python表示如下:

(lambda x: v1 if p1(x) else v2 if p2(x) else v3)

或以更清晰的方式格式化:

(lambda x:
     v1 if p1(x) else
     v2 if p2(x) else
     v3)

Python版本不是一个语句,而是一个表达式,其计算结果为一个值。

其他回答

我发现一种常见的交换机结构:

switch ...parameter...
case p1: v1; break;
case p2: v2; break;
default: v3;

可以用Python表示如下:

(lambda x: v1 if p1(x) else v2 if p2(x) else v3)

或以更清晰的方式格式化:

(lambda x:
     v1 if p1(x) else
     v2 if p2(x) else
     v3)

Python版本不是一个语句,而是一个表达式,其计算结果为一个值。

我一直喜欢这样做

result = {
  'a': lambda x: x * 5,
  'b': lambda x: x + 7,
  'c': lambda x: x - 2
}[value](x)

从这里开始

如果您不担心丢失案例套件中的语法高亮显示,可以执行以下操作:

exec {
    1: """
print ('one')
""", 
    2: """
print ('two')
""", 
    3: """
print ('three')
""",
}.get(value, """
print ('None')
""")

其中value是值。在C中,这将是:

switch (value) {
    case 1:
        printf("one");
        break;
    case 2:
        printf("two");
        break;
    case 3:
        printf("three");
        break;
    default:
        printf("None");
        break;
}

我们还可以创建一个helper函数来实现这一点:

def switch(value, cases, default):
    exec cases.get(value, default)

因此,我们可以将其用于一、二和三的示例:

switch(value, {
    1: """
print ('one')
    """, 
    2: """
print ('two')
    """, 
    3: """
print ('three')
    """,
}, """
print ('None')
""")

除了字典方法(我很喜欢,BTW),您还可以使用if elif else来获得switch/case/default功能:

if x == 'a':
    # Do the thing
elif x == 'b':
    # Do the other thing
if x in 'bc':
    # Fall-through by not using elif, but now the default case includes case 'a'!
elif x in 'xyz':
    # Do yet another thing
else:
    # Do the default

当然,这与switch/case不同——你不可能像放弃break语句那样轻易地通过,但你可以进行更复杂的测试。它的格式比一系列嵌套的if更好,尽管在功能上更接近。

到目前为止,已经有很多回答说,“我们在Python中没有开关,这样做吧”。然而,我想指出,switch语句本身是一个容易被滥用的构造,在大多数情况下可以而且应该避免,因为它们促进了惰性编程。案例说明:

def ToUpper(lcChar):
    if (lcChar == 'a' or lcChar == 'A'):
        return 'A'
    elif (lcChar == 'b' or lcChar == 'B'):
        return 'B'
    ...
    elif (lcChar == 'z' or lcChar == 'Z'):
        return 'Z'
    else:
        return None        # or something

现在,您可以使用switch语句(如果Python提供了switch语句)来执行此操作,但这会浪费您的时间,因为有些方法可以很好地执行此操作。或者,你有一些不太明显的东西:

def ConvertToReason(code):
    if (code == 200):
        return 'Okay'
    elif (code == 400):
        return 'Bad Request'
    elif (code == 404):
        return 'Not Found'
    else:
        return None

然而,这种操作可以而且应该用字典来处理,因为它会更快、更复杂、更不容易出错和更紧凑。

switch语句的绝大多数“用例”将属于这两种情况之一;如果你彻底考虑了你的问题,就没有什么理由使用它。

因此,与其问“我如何在Python中切换?”,或许我们应该问“我为什么要在Python中进行切换?”因为这往往是一个更有趣的问题,而且往往会暴露出您正在构建的任何设计中的缺陷。

现在,这并不是说也不应该使用开关。状态机、词法分析器、解析器和自动机都在某种程度上使用它们,一般来说,当你从对称输入开始到非对称输出时,它们会很有用;您只需要确保不要将开关用作锤子,因为您在代码中看到了一堆钉子。