我想用Python编写一个函数,根据输入索引的值返回不同的固定值。
在其他语言中,我会使用switch或case语句,但Python似乎没有switch语句。在此场景中,推荐的Python解决方案是什么?
我想用Python编写一个函数,根据输入索引的值返回不同的固定值。
在其他语言中,我会使用switch或case语句,但Python似乎没有switch语句。在此场景中,推荐的Python解决方案是什么?
当前回答
我要把我的两分钱放在这里。Python中没有case/switch语句的原因是因为Python遵循“只有一种正确的方法”的原则。很明显,您可以想出各种方法来重新创建switch/case功能,但实现这一点的Python方法是if/elf构造。即。,
if something:
return "first thing"
elif somethingelse:
return "second thing"
elif yetanotherthing:
return "third thing"
else:
return "default thing"
我只是觉得PEP 8应该在这里获得认可。Python的一个优点是它的简单和优雅。这在很大程度上源于PEP8中提出的原则,包括“只有一种正确的方法可以做某事。”
其他回答
您可以使用分派的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()
输出:
This is case 1
This is case 3
This is case 2
This is case 1
还可以使用列表存储案例,并通过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"
也在螺丝台上进行了解释。
我发现Python文档中的以下答案非常有用:
你可以通过一系列if…elif。。。埃利夫。。。其他的关于switch语句语法已经有了一些建议,但对于是否以及如何进行范围测试还没有达成共识。有关完整详细信息和当前状态,请参见PEP 275。
对于需要从大量可能性中进行选择的情况,可以创建一个字典,将大小写值映射到要调用的函数。例如:
def function_1(...):
...
functions = {'a': function_1,
'b': function_2,
'c': self.method_1, ...}
func = functions[value]
func()
对于在对象上调用方法,可以通过使用内置的getattr()来检索具有特定名称的方法来进一步简化:
def visit_a(self, ...):
...
...
def dispatch(self, value):
method_name = 'visit_' + str(value)
method = getattr(self, method_name)
method()
建议为方法名称使用前缀,例如本例中的visit_。如果没有这样的前缀,如果值来自不受信任的源,攻击者将能够调用对象上的任何方法。
与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。
除了字典方法(我很喜欢,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更好,尽管在功能上更接近。