简体   繁体   English

Python 中的 switch 语句的替换?

[英]Replacements for switch statement in Python?

I want to write a function in Python that returns different fixed values based on the value of an input index.我想在 Python 中写一个 function ,它根据输入索引的值返回不同的固定值。

In other languages I would use a switch or case statement, but Python does not appear to have a switch statement.在其他语言中,我会使用switchcase语句,但 Python 似乎没有switch语句。 What are the recommended Python solutions in this scenario?在这种情况下,推荐的 Python 解决方案是什么?

The original answer below was written in 2008. Since then, Python 3.10 (2021) introduced the match - case statement which provides a first-class implementation of a "switch" for Python.下面的原始答案是在 2008 年编写的。从那时起,Python 3.10 (2021) 引入了match - case语句,它为 Python 提供了“switch”的一流实现。 For example:例如:

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

The match - case statement is considerably more powerful than this simple example. match - case语句比这个简单的例子要强大得多。


You could use a dictionary:您可以使用字典:

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

If you'd like defaults, you could use the dictionary get(key[, default]) function:如果你想要默认值,你可以使用字典get(key[, default])函数:

def f(x):
    return {
        'a': 1,
        'b': 2
    }.get(x, 9)    # 9 will be returned default if x is not found

I've always liked doing it this way我一直喜欢这样做

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

From here从这里

In addition to the dictionary methods (which I really like, BTW), you can also use if - elif - else to obtain the switch / case / default functionality:除了字典方法(我真的很喜欢,顺便说一句),您还可以使用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

This of course is not identical to switch/case - you cannot have fall-through as easily as leaving off the break statement, but you can have a more complicated test.这当然与 switch/case 不同——你不能像离开break语句那样容易地失败,但你可以进行更复杂的测试。 Its formatting is nicer than a series of nested if s, even though functionally that's what it is closer to.它的格式比一系列嵌套的if更好,即使在功能上它更接近。

Python >= 3.10蟒蛇> = 3.10

Wow, Python 3.10+ now has a match / case syntax which is like switch/case and more!哇,Python 3.10+ 现在有一个match / case语法,就像switch/case等等!

PEP 634 -- Structural Pattern Matching PEP 634 -- 结构模式匹配

Selected features of match/case match/case的选定特征

1 - Match values: 1 - 匹配值:

Matching values is similar to a simple switch/case in another language:匹配值类似于另一种语言中的简单switch/case

match something:
    case 1 | 2 | 3:
        # Match 1-3.
    case _:
        # Anything else.
        # 
        # Match will throw an error if this is omitted 
        # and it doesn't match any of the other patterns.

2 - Match structural patterns: 2 - 匹配结构模式:

match something:
    case str() | bytes():  
        # Match a string like object.
    case [str(), int()]:
        # Match a `str` and an `int` sequence 
        # (`list` or a `tuple` but not a `set` or an iterator). 
    case [_, _]:
        # Match a sequence of 2 variables.
        # To prevent a common mistake, sequence patterns don’t match strings.
    case {"bandwidth": 100, "latency": 300}:
        # Match this dict. Extra keys are ignored.

3 - Capture variables 3 - 捕获变量

Parse an object;解析一个对象; saving it as variables:将其保存为变量:

match something:
    case [name, count]
        # Match a sequence of any two objects and parse them into the two variables.
    case [x, y, *rest]:
        # Match a sequence of two or more objects, 
        # binding object #3 and on into the rest variable.
    case bytes() | str() as text:
        # Match any string like object and save it to the text variable.

Capture variables can be useful when parsing data (such as JSON or HTML) that may come in one of a number of different patterns.在解析可能以多种不同模式之一出现的数据(例如 JSON 或 HTML)时,捕获变量可能很有用。

Capture variables is a feature.捕获变量是一项功能。 But it also means that you need to use dotted constants (ex: COLOR.RED ) only.但这也意味着您只需要使用带点的常量(例如: COLOR.RED )。 Otherwise, the constant will be treated as a capture variable and overwritten.否则,该常量将被视为捕获变量并被覆盖。

More sample usage : 更多示例用法

match something:
    case 0 | 1 | 2:
        # Matches 0, 1 or 2 (value).
        print("Small number")
    case [] | [_]:
        # Matches an empty or single value sequence (structure).
        # Matches lists and tuples but not sets.
        print("A short sequence")
    case str() | bytes():
        # Something of `str` or `bytes` type (data type).
        print("Something string-like")
    case _:
        # Anything not matched by the above.
        print("Something else")

Python <= 3.9 Python <= 3.9

My favorite Python recipe for switch/case was:我最喜欢的用于 switch/case 的 Python 配方是:

choices = {'a': 1, 'b': 2}
result = choices.get(key, 'default')

Short and simple for simple scenarios.简单的场景简短而简单。

Compare to 11+ lines of C code:与 11 多行 C 代码相比:

// C Language version of a simple 'switch/case'.
switch( key ) 
{
    case 'a' :
        result = 1;
        break;
    case 'b' :
        result = 2;
        break;
    default :
        result = -1;
}

You can even assign multiple variables by using tuples:您甚至可以使用元组分配多个变量:

choices = {'a': (1, 2, 3), 'b': (4, 5, 6)}
(result1, result2, result3) = choices.get(key, ('default1', 'default2', 'default3'))
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))

Usage:用法:

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

Tests:测试:

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

My favorite one is a really nice recipe .我最喜欢的是一个非常好的食谱 It's the closest one I've seen to actual switch case statements, especially in features.这是我见过的最接近实际 switch case 语句的语句,尤其是在特性方面。

class switch(object):
    def __init__(self, value):
        self.value = value
        self.fall = False

    def __iter__(self):
        """Return the match method once, then stop"""
        yield self.match
        raise StopIteration
    
    def match(self, *args):
        """Indicate whether or not to enter a case suite"""
        if self.fall or not args:
            return True
        elif self.value in args: # changed for v1.5, see below
            self.fall = True
            return True
        else:
            return False

Here's an example:这是一个例子:

# The following example is pretty much the exact use-case of a dictionary,
# but is included for its simplicity. Note that you can include statements
# in each suite.
v = 'ten'
for case in switch(v):
    if case('one'):
        print 1
        break
    if case('two'):
        print 2
        break
    if case('ten'):
        print 10
        break
    if case('eleven'):
        print 11
        break
    if case(): # default, could also just omit condition or 'if True'
        print "something else!"
        # No need to break here, it'll stop anyway

# break is used here to look as much like the real thing as possible, but
# elif is generally just as good and more concise.

# Empty suites are considered syntax errors, so intentional fall-throughs
# should contain 'pass'
c = 'z'
for case in switch(c):
    if case('a'): pass # only necessary if the rest of the suite is empty
    if case('b'): pass
    # ...
    if case('y'): pass
    if case('z'):
        print "c is lowercase!"
        break
    if case('A'): pass
    # ...
    if case('Z'):
        print "c is uppercase!"
        break
    if case(): # default
        print "I dunno what c was!"

# As suggested by Pierre Quentel, you can even expand upon the
# functionality of the classic 'case' statement by matching multiple
# cases in a single shot. This greatly benefits operations such as the
# uppercase/lowercase example above:
import string
c = 'A'
for case in switch(c):
    if case(*string.lowercase): # note the * for unpacking as arguments
        print "c is lowercase!"
        break
    if case(*string.uppercase):
        print "c is uppercase!"
        break
    if case('!', '?', '.'): # normal argument passing style also applies
        print "c is a sentence terminator!"
        break
    if case(): # default
        print "I dunno what c was!"

Some of the comments indicated that a context manager solution using with foo as case rather than for case in foo might be cleaner, and for large switch statements the linear rather than quadratic behavior might be a nice touch.一些评论表明,使用with foo as case而不是for case in foo的上下文管理器解决方案可能更干净,对于大型 switch 语句,线性而不是二次行为可能是一个不错的选择。 Part of the value in this answer with a for loop is the ability to have breaks and fallthrough, and if we're willing to play with our choice of keywords a little bit we can get that in a context manager too:这个带有 for 循环的答案的部分价值是能够突破和失败,如果我们愿意稍微使用我们选择的关键字,我们也可以在上下文管理器中得到它:

class Switch:
    def __init__(self, value):
        self.value = value
        self._entered = False
        self._broken = False
        self._prev = None

    def __enter__(self):
        return self

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

    def __call__(self, *values):
        if self._broken:
            return False
        
        if not self._entered:
            if values and self.value not in values:
                return False
            self._entered, self._prev = True, values
            return True
        
        if self._prev is None:
            self._prev = values
            return True
        
        if self._prev != values:
            self._broken = True
            return False
        
        if self._prev == values:
            self._prev = None
            return False
    
    @property
    def default(self):
        return self()

Here's an example:这是一个例子:

# Prints 'bar' then 'baz'.
with Switch(2) as case:
    while case(0):
        print('foo')
    while case(1, 2, 3):
        print('bar')
    while case(4, 5):
        print('baz')
        break
    while case.default:
        print('default')
        break
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

There's a pattern that I learned from Twisted Python code.我从 Twisted Python 代码中学到了一种模式。

class SMTP:
    def lookupMethod(self, command):
        return getattr(self, 'do_' + command.upper(), None)
    def do_HELO(self, rest):
        return 'Howdy ' + rest
    def do_QUIT(self, rest):
        return 'Bye'

SMTP().lookupMethod('HELO')('foo.bar.com') # => 'Howdy foo.bar.com'
SMTP().lookupMethod('QUIT')('') # => 'Bye'

You can use it any time you need to dispatch on a token and execute extended piece of code.您可以在需要发送令牌并执行扩展代码的任何时候使用它。 In a state machine you would have state_ methods, and dispatch on self.state .在状态机中,您将拥有state_方法,并在self.state上调度。 This switch can be cleanly extended by inheriting from base class and defining your own do_ methods.可以通过从基类继承并定义自己的do_方法来干净地扩展此开关。 Often times you won't even have do_ methods in the base class.很多时候你甚至不会在基类中有do_方法。

Edit: how exactly is that used编辑:究竟是如何使用的

In case of SMTP you will receive HELO from the wire.如果是 SMTP,您将收到来自网络的HELO The relevant code (from twisted/mail/smtp.py , modified for our case) looks like this相关代码(来自twisted/mail/smtp.py ,针对我们的案例进行了修改)看起来像这样

class SMTP:
    # ...

    def do_UNKNOWN(self, rest):
        raise NotImplementedError, 'received unknown command'

    def state_COMMAND(self, line):
        line = line.strip()
        parts = line.split(None, 1)
        if parts:
            method = self.lookupMethod(parts[0]) or self.do_UNKNOWN
            if len(parts) == 2:
                return method(parts[1])
            else:
                return method('')
        else:
            raise SyntaxError, 'bad syntax'

SMTP().state_COMMAND('   HELO   foo.bar.com  ') # => Howdy foo.bar.com

You'll receive ' HELO foo.bar.com ' (or you might get 'QUIT' or 'RCPT TO: foo' ).您将收到' HELO foo.bar.com ' (或者您可能会收到'QUIT''RCPT TO: foo' )。 This is tokenized into parts as ['HELO', 'foo.bar.com'] .这被标记为['HELO', 'foo.bar.com'] parts The actual method lookup name is taken from parts[0] .实际的方法查找名称取自parts[0]

(The original method is also called state_COMMAND , because it uses the same pattern to implement a state machine, ie getattr(self, 'state_' + self.mode) ) (原来的方法也叫state_COMMAND ,因为它使用相同的模式来实现状态机,即getattr(self, 'state_' + self.mode)

I'm just going to drop my two cents in here.我只是要把我的两分钱放在这里。 The reason there isn't a case/switch statement in Python is because Python follows the principle of "there's only one right way to do something". Python 中没有 case/switch 语句的原因是因为 Python 遵循“只有一种正确的方法可以做某事”的原则。 So obviously you could come up with various ways of recreating switch/case functionality, but the Pythonic way of accomplishing this is the if/elif construct.所以很明显,你可以想出各种方法来重新创建 switch/case 功能,但 Pythonic 的实现方式是 if/elif 构造。 Ie, IE,

if something:
    return "first thing"
elif somethingelse:
    return "second thing"
elif yetanotherthing:
    return "third thing"
else:
    return "default thing"

I just felt PEP 8 deserved a nod here.我只是觉得PEP 8值得在这里点头。 One of the beautiful things about Python is its simplicity and elegance. Python 的一大优点是它的简洁和优雅。 That is largely derived from principles laid out in PEP 8, including "There's only one right way to do something."这在很大程度上源于 PEP 8 中规定的原则,包括“做某事只有一种正确的方法”。

Let's say you don't want to just return a value, but want to use methods that change something on an object.假设您不想只返回一个值,而是想使用更改对象上某些内容的方法。 Using the approach stated here would be:使用此处所述的方法将是:

result = {
  'a': obj.increment(x),
  'b': obj.decrement(x)
}.get(value, obj.default(x))

Here Python evaluates all methods in the dictionary.在这里,Python 评估字典中的所有方法。

So even if your value is 'a', the object will get incremented and decremented by x.因此,即使您的值是 'a',该对象也会以 x 递增递减。

Solution:解决方案:

func, args = {
  'a' : (obj.increment, (x,)),
  'b' : (obj.decrement, (x,)),
}.get(value, (obj.default, (x,)))

result = func(*args)

So you get a list containing a function and its arguments.因此,您会得到一个包含函数及其参数的列表。 This way, only the function pointer and the argument list get returned, not evaluated.这样,只有函数指针和参数列表被返回,而不是被评估。 'result' then evaluates the returned function call. 'result' 然后评估返回的函数调用。

Solution to run functions:运行函数的解决方案:

result = {
    'case1':     foo1, 
    'case2':     foo2,
    'case3':     foo3,
}.get(option)(parameters_optional)

where foo1(), foo2() and foo3() are functions其中 foo1()、foo2() 和 foo3() 是函数

Example 1 (with parameters):示例 1 (带参数):

option = number['type']
result = {
    'number':     value_of_int,  # result = value_of_int(number['value'])
    'text':       value_of_text, # result = value_of_text(number['value'])
    'binary':     value_of_bin,  # result = value_of_bin(number['value'])
}.get(option)(value['value'])

Example 2 (no parameters):示例 2 (无参数):

option = number['type']
result = {
    'number':     func_for_number, # result = func_for_number()
    'text':       func_for_text,   # result = func_for_text()
    'binary':     func_for_bin,    # result = func_for_bin()
}.get(option)()

Example 4 (only values):示例 4 (仅值):

option = number['type']
result = {
    'number':    lambda: 10,       # result = 10
    'text':      lambda: 'ten',    # result = 'ten'
    'binary':    lambda: 0b101111, # result = 47
}.get(option)()

If you have a complicated case block you can consider using a function dictionary lookup table...如果您有一个复杂的案例块,您可以考虑使用函数字典查找表...

If you haven't done this before it's a good idea to step into your debugger and view exactly how the dictionary looks up each function.如果您之前没有这样做过,最好进入调试器并准确查看字典如何查找每个函数。

NOTE: Do not use "()" inside the case/dictionary lookup or it will call each of your functions as the dictionary / case block is created.注意:不要在案例/字典查找中使用“()”,否则它会在创建字典/案例块时调用您的每个函数。 Remember this because you only want to call each function once using a hash style lookup.请记住这一点,因为您只想使用哈希样式查找调用每个函数一次。

def first_case():
    print "first"

def second_case():
    print "second"

def third_case():
    print "third"

mycase = {
'first': first_case, #do not use ()
'second': second_case, #do not use ()
'third': third_case #do not use ()
}
myfunc = mycase['first']
myfunc()

If you're searching extra-statement, as "switch", I built a Python module that extends Python.如果您正在搜索额外语句,作为“开关”,我构建了一个扩展 Python 的 Python 模块。 It's called ESPY as "Enhanced Structure for Python" and it's available for both Python 2.x and Python 3.x.它被称为ESPY作为“Python 的增强结构”,它适用于 Python 2.x 和 Python 3.x。

For example, in this case, a switch statement could be performed by the following code:例如,在这种情况下,可以通过以下代码执行 switch 语句:

macro switch(arg1):
    while True:
        cont=False
        val=%arg1%
        socket case(arg2):
            if val==%arg2% or cont:
                cont=True
                socket
        socket else:
            socket
        break

That can be used like this:可以这样使用:

a=3
switch(a):
    case(0):
        print("Zero")
    case(1):
        print("Smaller than 2"):
        break
    else:
        print ("greater than 1")

So espy translate it in Python as:所以 espy 在 Python 中将其翻译为:

a=3
while True:
    cont=False
    if a==0 or cont:
        cont=True
        print ("Zero")
    if a==1 or cont:
        cont=True
        print ("Smaller than 2")
        break
    print ("greater than 1")
    break

Expanding on the "dict as switch" idea.扩展“dict as switch”的想法。 If you want to use a default value for your switch:如果您想为您的开关使用默认值:

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

Most of the answers here are pretty old, and especially the accepted ones, so it seems worth updating.这里的大多数答案都很老了,尤其是被接受的答案,所以似乎值得更新。

First, the official Python FAQ covers this, and recommends the elif chain for simple cases and the dict for larger or more complex cases.首先,官方Python 常见问题解答涵盖了这一点,并推荐elif链用于简单情况,而dict用于更大或更复杂的情况。 It also suggests a set of visit_ methods (a style used by many server frameworks) for some cases:它还针对某些情况建议了一组visit_方法(​​许多服务器框架使用的一种样式):

def dispatch(self, value):
    method_name = 'visit_' + str(value)
    method = getattr(self, method_name)
    method()

The FAQ also mentions PEP 275 , which was written to get an official once-and-for-all decision on adding C-style switch statements.常见问题解答还提到了PEP 275 ,它是为了获得有关添加 C 样式 switch 语句的官方一次性决定而编写的。 But that PEP was actually deferred to Python 3, and it was only officially rejected as a separate proposal, PEP 3103 .但是那个 PEP 实际上被推迟到 Python 3,它只是作为一个单独的提案被正式拒绝, PEP 3103 The answer was, of course, no—but the two PEPs have links to additional information if you're interested in the reasons or the history.答案当然是否定的——但如果您对原因或历史感兴趣,这两个 PEP 会提供指向其他信息的链接。


One thing that came up multiple times (and can be seen in PEP 275, even though it was cut out as an actual recommendation) is that if you're really bothered by having 8 lines of code to handle 4 cases, vs. the 6 lines you'd have in C or Bash, you can always write this:多次出现的一件事(并且可以在 PEP 275 中看到,尽管它被作为实际建议删掉了)是,如果你真的被 8 行代码处理 4 个案例所困扰,而 6你在 C 或 Bash 中的行,你总是可以这样写:

if x == 1: print('first')
elif x == 2: print('second')
elif x == 3: print('third')
else: print('did not place')

This isn't exactly encouraged by PEP 8, but it's readable and not too unidiomatic. PEP 8 并不完全鼓励这样做,但它是可读的并且不是太单调。


Over the more than a decade since PEP 3103 was rejected, the issue of C-style case statements, or even the slightly more powerful version in Go, has been considered dead;自从 PEP 3103 被拒绝后的十多年里,C 风格的 case 语句的问题,甚至是 Go 中稍微强大的版本,都被认为已经死了; whenever anyone brings it up on python-ideas or -dev, they're referred to the old decision.每当有人在 python-ideas 或 -dev 上提出它时,他们都会参考旧的决定。

However, the idea of full ML-style pattern matching arises every few years, especially since languages like Swift and Rust have adopted it.然而,完全 ML 风格的模式匹配的想法每隔几年就会出现一次,尤其是在 Swift 和 Rust 等语言已经采用它之后。 The problem is that it's hard to get much use out of pattern matching without algebraic data types.问题在于,如果没有代数数据类型,就很难从模式匹配中获得很多用途。 While Guido has been sympathetic to the idea, nobody's come up with a proposal that fits into Python very well.虽然 Guido 对这个想法表示同情,但没有人提出一个非常适合 Python 的建议。 (You can read my 2014 strawman for an example.) This could change with dataclass in 3.7 and some sporadic proposals for a more powerful enum to handle sum types, or with various proposals for different kinds of statement-local bindings (like PEP 3150 , or the set of proposals currently being discussed on -ideas). (您可以阅读我 2014 年的稻草人作为示例。)这可能会随着 3.7 中的dataclass和一些零星提议而改变,以提供更强大的enum来处理 sum 类型,或者针对不同类型的语句本地绑定(如PEP 3150 ,或当前正在讨论的一组提案-ideas)。 But so far, it hasn't.但到目前为止,还没有。

There are also occasionally proposals for Perl 6-style matching, which is basically a mishmash of everything from elif to regex to single-dispatch type-switching.偶尔也有 Perl 6 风格匹配的提议,这基本上是从elif到正则表达式再到单调度类型切换的所有内容的混搭。

I found that a common switch structure:我发现了一个常见的开关结构:

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

can be expressed in Python as follows:可以用 Python 表示如下:

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

or formatted in a clearer way:或以更清晰的方式格式化:

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

Instead of being a statement, the Python version is an expression, which evaluates to a value. Python 版本不是一个语句,而是一个表达式,它的计算结果是一个值。

The solutions I use:我使用的解决方案:

A combination of 2 of the solutions posted here, which is relatively easy to read and supports defaults.此处发布的 2 个解决方案的组合,相对易于阅读并支持默认设置。

result = {
  'a': lambda x: x * 5,
  'b': lambda x: x + 7,
  'c': lambda x: x - 2
}.get(whatToUse, lambda x: x - 22)(value)

where在哪里

.get('c', lambda x: x - 22)(23)

looks up "lambda x: x - 2" in the dict and uses it with x=23在字典中查找"lambda x: x - 2"并将其与x=23一起使用

.get('xxx', lambda x: x - 22)(44)

doesn't find it in the dict and uses the default "lambda x: x - 22" with x=44 .在 dict 中找不到它,并使用默认的"lambda x: x - 22"x=44

I didn't find the simple answer I was looking for anywhere on Google search.我在 Google 搜索的任何地方都没有找到我正在寻找的简单答案。 But I figured it out anyway.但我还是想通了。 It's really quite simple.这真的很简单。 Decided to post it, and maybe prevent a few less scratches on someone else's head.决定发布它,也许可以防止在别人的头上少一些划痕。 The key is simply "in" and tuples.关键是简单的“in”和元组。 Here is the switch statement behavior with fall-through, including RANDOM fall-through.下面是带有贯穿的 switch 语句行为,包括 RANDOM 贯穿。

l = ['Dog', 'Cat', 'Bird', 'Bigfoot',
     'Dragonfly', 'Snake', 'Bat', 'Loch Ness Monster']

for x in l:
    if x in ('Dog', 'Cat'):
        x += " has four legs"
    elif x in ('Bat', 'Bird', 'Dragonfly'):
        x += " has wings."
    elif x in ('Snake',):
        x += " has a forked tongue."
    else:
        x += " is a big mystery by default."
    print(x)

print()

for x in range(10):
    if x in (0, 1):
        x = "Values 0 and 1 caught here."
    elif x in (2,):
        x = "Value 2 caught here."
    elif x in (3, 7, 8):
        x = "Values 3, 7, 8 caught here."
    elif x in (4, 6):
        x = "Values 4 and 6 caught here"
    else:
        x = "Values 5 and 9 caught in default."
    print(x)

Provides:提供:

Dog has four legs
Cat has four legs
Bird has wings.
Bigfoot is a big mystery by default.
Dragonfly has wings.
Snake has a forked tongue.
Bat has wings.
Loch Ness Monster is a big mystery by default.

Values 0 and 1 caught here.
Values 0 and 1 caught here.
Value 2 caught here.
Values 3, 7, 8 caught here.
Values 4 and 6 caught here
Values 5 and 9 caught in default.
Values 4 and 6 caught here
Values 3, 7, 8 caught here.
Values 3, 7, 8 caught here.
Values 5 and 9 caught in default.

You can use a dispatched dict:您可以使用分派的字典:

#!/usr/bin/env python


def case1():
    print("This is case 1")

def case2():
    print("This is case 2")

def case3():
    print("This is case 3")


token_dict = {
    "case1" : case1,
    "case2" : case2,
    "case3" : case3,
}


def main():
    cases = ("case1", "case3", "case2", "case1")
    for case in cases:
        token_dict[case]()


if __name__ == '__main__':
    main()

Output:输出:

This is case 1
This is case 3
This is case 2
This is case 1
# simple case alternative

some_value = 5.0

# this while loop block simulates a case block

# case
while True:

    # case 1
    if some_value > 5:
        print ('Greater than five')
        break

    # case 2
    if some_value == 5:
        print ('Equal to five')
        break

    # else case 3
    print ( 'Must be less than 5')
    break
def f(x):
    dictionary = {'a':1, 'b':2, 'c':3}
    return dictionary.get(x,'Not Found') 
##Returns the value for the letter x;returns 'Not Found' if x isn't a key in the dictionary

I was quite confused after reading the accepted answer, but this cleared it all up:阅读接受的答案后,我很困惑,但这一切都清楚了:

def numbers_to_strings(argument):
    switcher = {
        0: "zero",
        1: "one",
        2: "two",
    }
    return switcher.get(argument, "nothing")

This code is analogous to:此代码类似于:

function(argument){
    switch(argument) {
        case 0:
            return "zero";
        case 1:
            return "one";
        case 2:
            return "two";
        default:
            return "nothing";
    }
}

Check theSource for more about dictionary mapping to functions.检查以获取有关字典映射到函数的更多信息。

I liked Mark Bies's answer我喜欢马克比斯的回答

Since the x variable must used twice, I modified the lambda functions to parameterless.由于x变量必须使用两次,我将 lambda 函数修改为无参数。

I have to run with results[value](value)我必须运行results[value](value)

In [2]: result = {
    ...:   'a': lambda x: 'A',
    ...:   'b': lambda x: 'B',
    ...:   'c': lambda x: 'C'
    ...: }
    ...: result['a']('a')
    ...: 
Out[2]: 'A'

In [3]: result = {
    ...:   'a': lambda : 'A',
    ...:   'b': lambda : 'B',
    ...:   'c': lambda : 'C',
    ...:   None: lambda : 'Nothing else matters'

    ...: }
    ...: result['a']()
    ...: 
Out[3]: 'A'

Edit: I noticed that I can use None type with with dictionaries.编辑:我注意到我可以在字典中使用None类型。 So this would emulate switch ; case else所以这将模拟switch ; case else switch ; case else

def f(x):
     return 1 if x == 'a' else\
            2 if x in 'bcd' else\
            0 #default

Short and easy to read, has a default value and supports expressions in both conditions and return values.简短易读,具有默认值并支持条件和返回值中的表达式。

However, it is less efficient than the solution with a dictionary.但是,它的效率低于使用字典的解决方案。 For example, Python has to scan through all the conditions before returning the default value.例如,Python 在返回默认值之前必须扫描所有条件。

Simple, not tested;简单,未经测试; each condition is evaluated independently: there is no fall-through, but all cases are evaluated (although the expression to switch on is only evaluated once), unless there is a break statement.每个条件都被独立评估:没有失败,但所有情况都被评估(尽管要打开的表达式只评估一次),除非有一个 break 语句。 For example,例如,

for case in [expression]:
    if case == 1:
        print(end='Was 1. ')

    if case == 2:
        print(end='Was 2. ')
        break

    if case in (1, 2):
        print(end='Was 1 or 2. ')

    print(end='Was something. ')

prints Was 1. Was 1 or 2. Was something.打印Was 1. Was 1 or 2. Was something. (Dammit! Why can't I have trailing whitespace in inline code blocks?) if expression evaluates to 1 , Was 2. if expression evaluates to 2 , or Was something. (该死!为什么内联代码块中不能有尾随空格?)如果expression的计算结果为1 ,则为Was 2.如果expression的计算结果为2 ,或者Was something. if expression evaluates to something else. if expression的计算结果为其他值。

A solution I tend to use which also makes use of dictionaries is:我倾向于使用的也使用字典的解决方案是:

def decision_time( key, *args, **kwargs):
    def action1()
        """This function is a closure - and has access to all the arguments"""
        pass
    def action2()
        """This function is a closure - and has access to all the arguments"""
        pass
    def action3()
        """This function is a closure - and has access to all the arguments"""
        pass

   return {1:action1, 2:action2, 3:action3}.get(key,default)()

This has the advantage that it doesn't try to evaluate the functions every time, and you just have to ensure that the outer function gets all the information that the inner functions need.这样做的好处是它不会每次都尝试评估函数,您只需确保外部函数获取内部函数所需的所有信息。

There have been a lot of answers so far that have said, "we don't have a switch in Python, do it this way".到目前为止,已经有很多答案说,“我们在 Python 中没有开关,就这样做吧”。 However, I would like to point out that the switch statement itself is an easily-abused construct that can and should be avoided in most cases because they promote lazy programming.然而,我想指出 switch 语句本身是一个容易被滥用的结构,在大多数情况下可以而且应该避免,因为它们促进了惰性编程。 Case in point:一个例子:

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

Now, you could do this with a switch-statement (if Python offered one) but you'd be wasting your time because there are methods that do this just fine.现在,您可以使用 switch 语句(如果 Python 提供一个)来执行此操作,但您会浪费您的时间,因为有些方法可以很好地执行此操作。 Or maybe, you have something less obvious:或者,你有一些不太明显的东西:

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

However, this sort of operation can and should be handled with a dictionary because it will be faster, less complex, less prone to error and more compact.然而,这种操作可以而且应该用字典来处理,因为它会更快、更简单、更不容易出错并且更紧凑。

And the vast majority of "use cases" for switch statements will fall into one of these two cases;而switch语句的绝大多数“用例”都属于这两种情况之一; there's just very little reason to use one if you've thought about your problem thoroughly.如果您已经彻底考虑过您的问题,那么几乎没有理由使用它。

So, rather than asking "how do I switch in Python?", perhaps we should ask, "why do I want to switch in Python?"所以,与其问“我如何在 Python 中切换?”,或许我们应该问,“我为什么要在 Python 中切换?” because that's often the more interesting question and will often expose flaws in the design of whatever you're building.因为这通常是更有趣的问题,并且经常会暴露您正在构建的任何设计中的缺陷。

Now, that isn't to say that switches should never be used either.现在,这并不是说也不应该使用开关。 State machines, lexers, parsers and automata all use them to some degree and, in general, when you start from a symmetrical input and go to an asymmetrical output they can be useful;状态机、词法分析器、解析器和自动机都在某种程度上使用它们,一般来说,当您从对称输入开始并转到非对称输出时,它们会很有用; you just need to make sure that you don't use the switch as a hammer because you see a bunch of nails in your code.您只需要确保不要将开关用作锤子,因为您会在代码中看到一堆钉子。

Defining:定义:

def switch1(value, options):
  if value in options:
    options[value]()

allows you to use a fairly straightforward syntax, with the cases bundled into a map:允许您使用相当简单的语法,将案例捆绑到地图中:

def sample1(x):
  local = 'betty'
  switch1(x, {
    'a': lambda: print("hello"),
    'b': lambda: (
      print("goodbye," + local),
      print("!")),
    })

I kept trying to redefine switch in a way that would let me get rid of the "lambda:", but gave up.我一直试图以一种可以让我摆脱“lambda:”的方式重新定义 switch,但最终放弃了。 Tweaking the definition:调整定义:

def switch(value, *maps):
  options = {}
  for m in maps:
    options.update(m)
  if value in options:
    options[value]()
  elif None in options:
    options[None]()

Allowed me to map multiple cases to the same code, and to supply a default option:允许我将多个案例映射到相同的代码,并提供默认选项:

def sample(x):
  switch(x, {
    _: lambda: print("other") 
    for _ in 'cdef'
    }, {
    'a': lambda: print("hello"),
    'b': lambda: (
      print("goodbye,"),
      print("!")),
    None: lambda: print("I dunno")
    })

Each replicated case has to be in its own dictionary;每个重复的案例都必须在自己的字典中; switch() consolidates the dictionaries before looking up the value. switch() 在查找值之前合并字典。 It's still uglier than I'd like, but it has the basic efficiency of using a hashed lookup on the expression, rather than a loop through all the keys.它仍然比我想要的更难看,但它具有在表达式上使用散列查找的基本效率,而不是遍历所有键的循环。

I think the best way is to use the Python language idioms to keep your code testable .我认为最好的方法是使用 Python 语言习语来保持您的代码可测试 As showed in previous answers, I use dictionaries to take advantage of python structures and language and keep the "case" code isolated in different methods.如之前的答案所示,我使用字典来利用 python 结构和语言,并以不同的方法隔离“案例”代码。 Below there is a class, but you can use directly a module, globals and functions.下面有一个类,但您可以直接使用模块、全局变量和函数。 The class has methods that can be tested with isolation .该类具有可以使用隔离测试的方法。

Depending to your needs, you can play with static methods and attributes too.根据您的需要,您也可以使用静态方法和属性。

class ChoiceManager:

    def __init__(self):
        self.__choice_table = \
        {
            "CHOICE1" : self.my_func1,
            "CHOICE2" : self.my_func2,
        }

    def my_func1(self, data):
        pass

    def my_func2(self, data):
        pass

    def process(self, case, data):
        return self.__choice_table[case](data)

ChoiceManager().process("CHOICE1", my_data)

It is possible to take advantage of this method using also classes as keys of "__choice_table".也可以使用类作为“__choice_table”的键来利用此方法 In this way you can avoid isinstance abuse and keep all clean and testable.通过这种方式,您可以避免isinstance 滥用并保持所有内容的清洁和可测试。

Supposing you have to process a lot of messages or packets from the net or your MQ.假设您必须处理来自网络或您的 MQ 的大量消息或数据包。 Every packet has its own structure and its management code (in a generic way).每个数据包都有自己的结构和管理代码(以通用方式)。

With the above code it is possible to do something like this:使用上面的代码可以做这样的事情:

class PacketManager:

    def __init__(self):
        self.__choice_table = \
        {
            ControlMessage : self.my_func1,
            DiagnosticMessage : self.my_func2,
        }

    def my_func1(self, data):
        # process the control message here
        pass

    def my_func2(self, data):
        # process the diagnostic message here
        pass

    def process(self, pkt):
        return self.__choice_table[pkt.__class__](pkt)

pkt = GetMyPacketFromNet()
PacketManager().process(pkt)


# isolated test or isolated usage example
def test_control_packet():
    p = ControlMessage()
    PacketManager().my_func1(p)

So complexity is not spread in the code flow, but it is rendered in the code structure .所以复杂性并没有散布在代码流中,而是呈现在代码结构中。

Expanding on Greg Hewgill's answer - We can encapsulate the dictionary-solution using a decorator:扩展Greg Hewgill 的答案- 我们可以使用装饰器封装字典解决方案:

def case(callable):
    """switch-case decorator"""
    class case_class(object):
        def __init__(self, *args, **kwargs):
            self.args = args
            self.kwargs = kwargs

        def do_call(self):
            return callable(*self.args, **self.kwargs)

return case_class

def switch(key, cases, default=None):
    """switch-statement"""
    ret = None
    try:
        ret = case[key].do_call()
    except KeyError:
        if default:
            ret = default.do_call()
    finally:
        return ret

This can then be used with the @case -decorator这可以与@case -decorator 一起使用

@case
def case_1(arg1):
    print 'case_1: ', arg1

@case
def case_2(arg1, arg2):
    print 'case_2'
    return arg1, arg2

@case
def default_case(arg1, arg2, arg3):
    print 'default_case: ', arg1, arg2, arg3

ret = switch(somearg, {
    1: case_1('somestring'),
    2: case_2(13, 42)
}, default_case(123, 'astring', 3.14))

print ret

The good news are that this has already been done in NeoPySwitch -module.好消息是这已经在NeoPySwitch模块中完成了。 Simply install using pip:只需使用 pip 安装:

pip install NeoPySwitch

If you don't worry losing syntax highlight inside the case suites, you can do the following:如果您不担心在案例套件中丢失语法高亮,您可以执行以下操作:

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

Where value is the value. value就是价值。 In C, this would be:在 C 中,这将是:

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

We can also create a helper function to do this:我们还可以创建一个辅助函数来执行此操作:

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

So we can use it like this for the example with one, two and three:因此,我们可以像这样使用它来作为一、二和三的示例:

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

Just mapping some a key to some code is not really an issue as most people have shown using the dict.正如大多数人使用字典所展示的那样,仅仅将一些键映射到一些代码并不是一个真正的问题。 The real trick is trying to emulate the whole drop through and break thing.真正的诀窍是试图模仿整个穿透和破坏的东西。 I don't think I've ever written a case statement where I used that "feature".我不认为我曾经写过使用该“功能”的案例陈述。 Here's a go at drop through.这是一个通过。

def case(list): reduce(lambda b, f: (b | f[0], {False:(lambda:None),True:f[1]}[b | f[0]]())[0], list, False)

case([
    (False, lambda:print(5)),
    (True, lambda:print(4))
])

I was really imagining it as a single statement.我真的把它想象成一个单一的陈述。 I hope you'll pardon the silly formatting.我希望你能原谅愚蠢的格式。

reduce(
    initializer=False,
    function=(lambda b, f:
        ( b | f[0]
        , { False: (lambda:None)
          , True : f[1]
          }[b | f[0]]()
        )[0]
    ),
    iterable=[
        (False, lambda:print(5)),
        (True, lambda:print(4))
    ]
)

I hope that's valid Python code.我希望这是有效的 Python 代码。 It should give you drop through.它应该让你通过。 Of course the Boolean checks could be expressions and if you wanted them to be evaluated lazily you could wrap them all in a lambda.当然,布尔检查可以是表达式,如果您希望它们被懒惰地评估,您可以将它们全部包装在 lambda 中。 It wouldn't be to hard to make it accept after executing some of the items in the list either.在执行列表中的某些项目后使其接受也不难。 Just make the tuple (bool, bool, function) where the second bool indicates whether or not to break or drop through.只需创建元组 (bool, bool, function),其中第二个 bool 指示是否突破或丢弃。

I've found the following answer from Python documentation most helpful:我从Python 文档中发现以下答案最有帮助:

You can do this easily enough with a sequence of if... elif... elif... else .您可以使用一系列if... elif... elif... else轻松完成此操作。 There have been some proposals for switch statement syntax, but there is no consensus (yet) on whether and how to do range tests.已经有一些关于 switch 语句语法的提议,但是关于是否以及如何进行范围测试还没有达成共识。 See PEP 275 for complete details and the current status.有关完整的详细信息和当前状态,请参阅 PEP 275。

For cases where you need to choose from a very large number of possibilities, you can create a dictionary mapping case values to functions to call.对于需要从大量可能性中进行选择的情况,您可以创建一个字典,将案例值映射到要调用的函数。 For example:例如:

def function_1(...):
    ...

functions = {'a': function_1,
             'b': function_2,
             'c': self.method_1, ...}

func = functions[value]
func()

For calling methods on objects, you can simplify yet further by using the getattr() built-in to retrieve methods with a particular name:对于调用对象的方法,您可以通过使用内置的 getattr() 来检索具有特定名称的方法来进一步简化:

def visit_a(self, ...):
    ...
...

def dispatch(self, value):
    method_name = 'visit_' + str(value)
    method = getattr(self, method_name)
    method()

It's suggested that you use a prefix for the method names, such as visit_ in this example.建议您为方法名称使用前缀,例如本例中的visit_ Without such a prefix, if values are coming from an untrusted source, an attacker would be able to call any method on your object.如果没有这样的前缀,如果值来自不受信任的来源,攻击者将能够调用您对象上的任何方法。

As a minor variation on Mark Biek's answer , for uncommon cases like this duplicate where the user has a bunch of function calls to delay with arguments to pack in (and it isn't worth building a bunch of functions out-of-line), instead of this:作为Mark Biek 答案的一个小变化,对于这种不常见的情况,比如用户有一堆函数调用要延迟并带有要打包的参数(并且不值得构建一堆函数外线),而不是这个:

d = {
    "a1": lambda: a(1),
    "a2": lambda: a(2),
    "b": lambda: b("foo"),
    "c": lambda: c(),
    "z": lambda: z("bar", 25),
    }
return d[string]()

… you can do this: … 你可以这样做:

d = {
    "a1": (a, 1),
    "a2": (a, 2),
    "b": (b, "foo"),
    "c": (c,)
    "z": (z, "bar", 25),
    }
func, *args = d[string]
return func(*args)

This is certainly shorter, but whether it's more readable is an open question…这当然更短,但它是否更具可读性是一个悬而未决的问题……


I think it might be more readable (although not briefer) to switch from lambda to partial for this particular use:我认为对于这种特殊用途,从lambda切换到partial可能更具可读性(尽管不是更简洁):

d = {
    "a1": partial(a, 1),
    "a2": partial(a, 2),
    "b": partial(b, "foo"),
    "c": c,
    "z": partial(z, "bar", 25),
    }
return d[string]()

… which has the advantage of working nicely with keyword arguments as well: …它的优点是可以很好地使用关键字参数:

d = {
    "a1": partial(a, 1),
    "a2": partial(a, 2),
    "b": partial(b, "foo"),
    "c": c,
    "k": partial(k, key=int),
    "z": partial(z, "bar", 25),
    }
return d[string]()

I've made a switch case implementation that doesn't quite use ifs externally (it still uses an if in the class).我制作了一个在外部不太使用ifsswitch case实现(它仍然在类中使用if )。

class SwitchCase(object):
    def __init__(self):
        self._cases = dict()

    def add_case(self,value, fn):
        self._cases[value] = fn

    def add_default_case(self,fn):
        self._cases['default']  = fn

    def switch_case(self,value):
        if value in self._cases.keys():
            return self._cases[value](value)
        else:
            return self._cases['default'](0)

Use it like this:像这样使用它:

from switch_case import SwitchCase
switcher = SwitchCase()
switcher.add_case(1, lambda x:x+1)
switcher.add_case(2, lambda x:x+3)
switcher.add_default_case(lambda _:[1,2,3,4,5])

print switcher.switch_case(1) #2
print switcher.switch_case(2) #5
print switcher.switch_case(123) #[1, 2, 3, 4, 5]

Although there are already enough answers, I want to point a simpler and more powerful solution:虽然已经有了足够多的答案,但我想指出一个更简单、更强大的解决方案:

class Switch:
    def __init__(self, switches):
        self.switches = switches
        self.between = len(switches[0]) == 3

    def __call__(self, x):
        for line in self.switches:
            if self.between:
                if line[0] <= x < line[1]:
                    return line[2]
            else:
                if line[0] == x:
                    return line[1]
        return None


if __name__ == '__main__':
    between_table = [
        (1, 4, 'between 1 and 4'),
        (4, 8, 'between 4 and 8')
    ]

    switch_between = Switch(between_table)

    print('Switch Between:')
    for i in range(0, 10):
        if switch_between(i):
            print('{} is {}'.format(i, switch_between(i)))
        else:
            print('No match for {}'.format(i))


    equals_table = [
        (1, 'One'),
        (2, 'Two'),
        (4, 'Four'),
        (5, 'Five'),
        (7, 'Seven'),
        (8, 'Eight')
    ]
    print('Switch Equals:')
    switch_equals = Switch(equals_table)
    for i in range(0, 10):
        if switch_equals(i):
            print('{} is {}'.format(i, switch_equals(i)))
        else:
            print('No match for {}'.format(i))

Output:输出:

Switch Between:
No match for 0
1 is between 1 and 4
2 is between 1 and 4
3 is between 1 and 4
4 is between 4 and 8
5 is between 4 and 8
6 is between 4 and 8
7 is between 4 and 8
No match for 8
No match for 9

Switch Equals:
No match for 0
1 is One
2 is Two
No match for 3
4 is Four
5 is Five
No match for 6
7 is Seven
8 is Eight
No match for 9

Similar to this answer by abarnert , here is a solution specifically for the use case of calling a single function for each 'case' in the switch, while avoiding the lambda or partial for ultra-conciseness while still being able to handle keyword arguments:abarnert 的这个答案类似,这里有一个专门针对在 switch 中为每个“case”调用单个函数的用例的解决方案,同时避免使用lambdapartial以获得超简洁性,同时仍然能够处理关键字参数:

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

Example usage:示例用法:

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)

Note that this is chaining calls, ie switch(3)(...)(...)(...) .请注意,这是链接调用,即switch(3)(...)(...)(...) Don't put commas in between.中间不要加逗号。 It's also important to put it all in one expression, which is why I've used extra parentheses around the main call for implicit line continuation.将所有内容放在一个表达式中也很重要,这就是为什么我在主调用周围使用额外的括号来实现隐式行继续。

The above example will raise an error if you switch on a value that is not handled, eg switch(5)(1, ...)(2, ...)(3, ...) .如果您打开未处理的值,例如switch(5)(1, ...)(2, ...)(3, ...)上面的示例将引发错误。 You can provide a default value instead, eg switch(5, default=-1)... returns -1 .您可以改为提供默认值,例如switch(5, default=-1)...返回-1

If you are really just returning a predetermined, fixed value, you could create a dictionary with all possible input indexes as the keys, along with their corresponding values.如果您真的只是返回一个预定的固定值,您可以创建一个字典,其中所有可能的输入索引作为键,以及它们的相应值。 Also, you might not really want a function to do this - unless you're computing the return value somehow.此外,您可能并不真的想要一个函数来执行此操作 - 除非您以某种方式计算返回值。

Oh, and if you feel like doing something switch-like, see here .哦,如果你想做一些类似开关的事情,请看这里

Also use the list for storing the cases, and call corresponding the function by select -也使用列表存储案例,并通过选择调用相应的功能 -

cases = ['zero()', 'one()', 'two()', 'three()']

def zero():
  print "method for 0 called..."
def one():
  print "method for 1 called..."
def two():
  print "method for 2 called..."
def three():
  print "method for 3 called..."

i = int(raw_input("Enter choice between 0-3 "))

if(i<=len(cases)):
  exec(cases[i])
else:
  print "wrong choice"

Also explained at screwdesk .螺丝桌也有解释。

The following works for my situation when I need a simple switch-case to call a bunch of methods and not to just print some text.当我需要一个简单的 switch-case 来调用一堆方法而不是仅仅打印一些文本时,以下适用于我的情况。 After playing with lambda and globals it hit me as the simplest option for me so far.在玩过 lambda 和 globals 之后,它对我来说是迄今为止最简单的选择。 Maybe it will help someone also:也许它也会帮助某人:

def start():
    print("Start")

def stop():
    print("Stop")

def print_help():
    print("Help")

def choose_action(arg):
    return {
        "start": start,
        "stop": stop,
        "help": print_help,
    }.get(arg, print_help)

argument = sys.argv[1].strip()
choose_action(argument)()  # calling a method from the given string

And another option:还有另一个选择:

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) )

Easy to remember:容易记住:

while True:
    try:
        x = int(input("Enter a numerical input: "))
    except:
        print("Invalid input - please enter a Integer!");
    if x==1:
        print("good");
    elif x==2:
        print("bad");
    elif x==3:
        break
    else:
        print ("terrible");

A switch statement is just syntactic sugar for if/elif/else. switch 语句只是 if/elif/else 的语法糖。 What any control statement is doing is delegating the job based on certain condition is being fulfilled - decision path.任何控制语句所做的都是根据正在满足的特定条件委派工作 - 决策路径。 For wrapping that into a module and being able to call a job based on its unique id, one can use inheritance and the fact that any method in Python is virtual, to provide the derived class specific job implementation, as a specific "case" handler:为了将其包装到模块中并能够根据其唯一 ID 调用作业,可以使用继承以及 Python 中的任何方法都是虚拟的这一事实,以提供派生类特定的作业实现,作为特定的“案例”处理程序:

#!/usr/bin/python

import sys

class Case(object):
    """
        Base class which specifies the interface for the "case" handler.
        The all required arbitrary arguments inside "execute" method will be
        provided through the derived class
        specific constructor

        @note in Python, all class methods are virtual
    """
    def __init__(self, id):
        self.id = id

    def pair(self):
        """
            Pairs the given id of the "case" with
            the instance on which "execute" will be called
        """
        return (self.id, self)

    def execute(self): # Base class virtual method that needs to be overridden
        pass

class Case1(Case):
    def __init__(self, id, msg):
        self.id = id
        self.msg = msg
    def execute(self): # Override the base class method
        print("<Case1> id={}, message: \"{}\"".format(str(self.id), self.msg))

class Case2(Case):
    def __init__(self, id, n):
        self.id = id
        self.n = n
    def execute(self): # Override the base class method
        print("<Case2> id={}, n={}.".format(str(self.id), str(self.n)))
        print("\n".join(map(str, range(self.n))))


class Switch(object):
    """
        The class which delegates the jobs
        based on the given job id
    """
    def __init__(self, cases):
        self.cases = cases # dictionary: time complexity for the access operation is 1
    def resolve(self, id):

        try:
            cases[id].execute()
        except KeyError as e:
            print("Given id: {} is wrong!".format(str(id)))



if __name__ == '__main__':

    # Cases
    cases=dict([Case1(0, "switch").pair(), Case2(1, 5).pair()])

    switch = Switch(cases)

    # id will be dynamically specified
    switch.resolve(0)
    switch.resolve(1)
    switch.resolve(2)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM