我们知道,python是没有switch语句的,所以当我们要实现这样结构的逻辑时:
var index = 10 switch index { case 100 : print( "index 的值为 100") case 10,15 : print( "index 的值为 10 或 15") case 5 : print( "index 的值为 5") default : print( "默认 case") }
经常需要用多个if-else来实现。除此之外,我们还可以考虑用字典对应提取的方式来实现,下面我们给出四种实现switch的方法,并对比这四种方法的运行时间
something = 'something' # 第一种,多次使用if-else结构 if something == 'this': the_thing = 1 elif something == 'that': the_thing = 2 elif something == 'there': the_thing = 3 else: the_thing = 4 # 第二种,用get设置默认值的字典提取 options = {'this': 1, 'that': 2, 'there': 3} the_thing = options.get(something, 4) # 第三种,用if-else配合不设置默认值的字典提取 options = {'this': 1, 'that': 2, 'there': 3} if something in options: the_thing = options[something] else: the_thing = 4 # 第四种,用collections模块设置默认值进行字典提取 from collections import defaultdict default_options = defaultdict(lambda: 4, {'this': 1, 'that': 2, 'there': 3}) the_thing = default_options[something]
下面我们对比一下这几种方式提取的速度,分成两种情况
- 判断的内容在字典中
- 判断的内容不在字典中
在ifelse.py文件中输入如下内容
import time from collections import defaultdict # 计算运行时间的装饰器 def run_time(func): def wrapper(*args, **kw): start = time.time() func(*args, **kw) end = time.time() print('running', end-start, 's') return wrapper # 准备好两个字典 options = {'this': 1, 'that': 2, 'there': 3} default_options = defaultdict(lambda: 4, {'this': 1, 'that': 2, 'there': 3}) # 四种方法都定义成函数 # 接受参数something即待判断值 # 每次循环10000000次 @run_time def first(something): for i in range(10000000): if something == 'this': the_thing = 1 elif something == 'that': the_thing = 2 elif something == 'there': the_thing = 3 else: the_thing = 4 @run_time def second(something): for i in range(10000000): the_thing = options.get(something, 4) @run_time def third(something): for i in range(10000000): if something in options: the_thing = options[something] else: the_thing = 4 @run_time def forth(something): for i in range(10000000): the_thing = default_options[something] # 调用函数 if __name__ == '__main__': # 判断的内容不在字典中 first('something') second('something') third('something') forth('something') print('-'*20) # 判断的内容在字典中 first('this') second('this') third('this') forth('this')
在命令行多次运行
python ifelse.py
得到结果如下
-------------第一次--------------- running 1.8487958908081055 s running 1.63755202293396 s running 0.7807505130767822 s running 0.6786513328552246 s -------------------- running 0.7807483673095703 s running 2.075996160507202 s running 1.0349910259246826 s running 0.740731954574585 s -------------第二次--------------- running 1.7757258415222168 s running 1.6395549774169922 s running 0.8408102989196777 s running 0.7977871894836426 s -------------------- running 0.710662841796875 s running 1.9098539352416992 s running 1.042982578277588 s running 0.8197875022888184 s -------------第三次--------------- running 1.5885050296783447 s running 1.8237719535827637 s running 0.9819226264953613 s running 0.78375244140625 s -------------------- running 0.6226155757904053 s running 1.634549617767334 s running 0.947911262512207 s running 0.6586313247680664 s
从结果中可以看出
1.四种方法之间的对比,后两种方法明显比前两种方法快,且最后一种方法总是最快的。
2.待判断内容是否在字典中设置的对比
- 第一种全程if-else判断的情况下,早判断出来程序就会早结束,所以if-else判断的内容顺序是有讲究的
- 而从字典里提取则没有看出显著的不同
由于使用collections模块中的defaultdict虽然最快,但是会占用较多内存,所以最推荐的是第三种方法,使用if-else配合无默认字典提取方法。
在Python中,没有内置的switch语句,但是可以使用多种方式实现类似switch的操作。以下是几种实现方法:
- 使用字典:
pythondef switch(key): return { 'a': 'case a', 'b': 'case b', 'c': 'case c', }.get(key, 'default') print(switch('a')) # 输出: case a print(switch('d')) # 输出: default
- 使用 if-elif-else 语句:
pythondef switch(key): if key == 'a': return 'case a' elif key == 'b': return 'case b' elif key == 'c': return 'case c' else: return 'default' print(switch('a')) # 输出: case a print(switch('d')) # 输出: default
- 使用函数装饰器和字典:
pythondef switch(key): @dict_of_functions.get(key, lambda: 'default') def default(): return 'case a' def case_b(): return 'case b' def case_c(): return 'case c' dict_of_functions = { 'a': default, 'b': case_b, 'c': case_c, } return switch(key)() print(switch('a')) # 输出: case a print(switch('d')) # 输出: default
- 使用类装饰器和字典:
pythonclass Switch: def __init__(self, key): self.key = key @property def case(self): return { 'a': 'case a', 'b': 'case b', 'c': 'case c', }.get(self.key, 'default') print(Switch('a').case) # 输出: case a print(Switch('d').case) # 输出: default
以上就是Python中实现类似switch操作的几种方法。
python语言中,没有内置switch函数,如果用if-else语句的话,当分支数量很大时,会显得很臃肿,下面是使用python中的字典,实现switch语句功能的方法。
# 设置flag的值,用于选择执行哪个函数 flag = 0 # 设置自定义函数 def get_function_1(): # 函数功能 return 'Function_1' def get_function_2(): # 函数功能 return 'Function_2' def get_function_3(): # 函数功能 return 'Function_3' def get_default(): # 函数功能 return 'Others' # 字典中不同的值对应不同的自定义函数 switcher = { 0: get_function_1, 1: get_function_2, 2: get_function_3 } # 根据flag的值决定执行哪一个函数,如果输入的值在字典中没有,则执行get_default函数 output = switcher.get(flag, get_default)() print("The output of switcher is: ", output)
如果语句不复杂,也可以使用lambda表达式,可以使代码更简洁,lambda表达式介绍见
Python lambda介绍 - Goodpy - 博客园www.cnblogs.com/evening/archive/2012/03/29/2423554.html
下面是利用了字典和lambda表达式,实现switch语句功能
flag = 0 # 如果字典中没有flag的值,则执行get_default函数 def get_default(x): # 函数功能 return 'None' switcher = { 0: lambda x:x+1, 1: lambda x:x**2, 2: lambda x:abs(x) } output = switcher.get(flag, get_default)(5) print("The output of switcher is: ", output)
作者:书海阅读岛
链接:https://www.zhihu.com/question/591024612/answer/2953371599
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Python已有特性
- Python中的函数是可以作为变量存在的,也就是可以将函数复制给变量,变量可以作为字典的value存在,也就是函数可以作为字典的value,对应了switch中的基本特性1
- if-else可以让程序存在多种不同的分支,可以用来实现基本特性2中的默认逻辑
- 字典的key和value是一对一或者多对一的,就是每个key对应一个value,但是一个value可以有多个key;这点对应了switch的基本特性3
需要添加的特性
从Python已有特性上来说,我们看起来不需要添加什么新的新特性,只需要把已有特性组合下就行
组合特性
这里以一个课本中的题目来做例子:百分制转字母分,也就是——90分及以上是A,80分及以上是B,70分及以上是C,60分及以上是D,60分以下都是E
- 定义一个字典,key是条件,value是函数,把条件和对应的逻辑组合起来
# 定义各种函数 def is_a(): return 'A' def is_b(): return 'B' def is_c(): return 'C' def is_d(): return 'D' def is_e(): return 'E' # 为了方便处理,分数先除以10向下取整,按取整结果选执行逻辑 # 定义switch-case跳转表,这里90分及以上是A,80分及以上是B,70分及以上是C,60分及以上是D switch_dict = { 10: is_a, 9: is_a, 8: is_b, 7: is_c, 6: is_d, }
- 用if-else语句处理能找的到条件的执行逻辑和找不到条件的执行逻辑,也就是实现匹配和默认情况
if score_div_ten in switch_dict.keys(): # 在switch_dict里有对应的逻辑 return switch_dict[score_div_ten]() else: # 没在switch_dict里的按默认逻辑处理 return is_e()
全部代码
#!/usr/bin/python # -*- coding: utf8 -*- import math def is_a(): return 'A' def is_b(): return 'B' def is_c(): return 'C' def is_d(): return 'D' def is_e(): return 'E' def score_to_af(score): # 分数除以10以后向下取整,算是属于几十分 score_div_ten = math.floor(score / 10) # 定义switch-case跳转表,这里90分及以上是A,80分及以上是B,70分及以上是C,60分及以上是D,60分以下都是E(default) switch_dict = { 10: is_a, 9: is_a, 8: is_b, 7: is_c, 6: is_d, } if score_div_ten in switch_dict.keys(): return switch_dict[score_div_ten]() else: return is_e() if __name__ == '__main__': for score in range(0, 101): print('score:%d, af:%s' % (score, score_to_af(score)))
执行结果
score:0, af:E score:1, af:E score:2, af:E score:3, af:E score:4, af:E score:5, af:E score:6, af:E score:7, af:E score:8, af:E score:9, af:E score:10, af:E score:11, af:E score:12, af:E score:13, af:E score:14, af:E score:15, af:E score:16, af:E score:17, af:E score:18, af:E score:19, af:E score:20, af:E score:21, af:E score:22, af:E score:23, af:E score:24, af:E score:25, af:E score:26, af:E score:27, af:E score:28, af:E score:29, af:E score:30, af:E score:31, af:E score:32, af:E score:33, af:E score:34, af:E score:35, af:E score:36, af:E score:37, af:E score:38, af:E score:39, af:E score:40, af:E score:41, af:E score:42, af:E score:43, af:E score:44, af:E score:45, af:E score:46, af:E score:47, af:E score:48, af:E score:49, af:E score:50, af:E score:51, af:E score:52, af:E score:53, af:E score:54, af:E score:55, af:E score:56, af:E score:57, af:E score:58, af:E score:59, af:E score:60, af:D score:61, af:D score:62, af:D score:63, af:D score:64, af:D score:65, af:D score:66, af:D score:67, af:D score:68, af:D score:69, af:D score:70, af:C score:71, af:C score:72, af:C score:73, af:C score:74, af:C score:75, af:C score:76, af:C score:77, af:C score:78, af:C score:79, af:C score:80, af:B score:81, af:B score:82, af:B score:83, af:B score:84, af:B score:85, af:B score:86, af:B score:87, af:B score:88, af:B score:89, af:B score:90, af:A score:91, af:A score:92, af:A score:93, af:A score:94, af:A score:95, af:A score:96, af:A score:97, af:A score:98, af:A score:99, af:A score:100, af:A
思路2的思考过程
一段if-elif-else代码
def score_to_af2(score): # 分数除以10以后向下取整,算是属于几十分 score_div_ten = math.floor(score / 10) if 9 <= score_div_ten <= 10: result = 'A' elif score_div_ten == 8: result = 'B' elif score_div_ten == 7: result = 'C' elif score_div_ten == 6: result = 'D' else: result = 'E' return result
条件和执行逻辑
很简单的代码,条件和一行简单的逻辑的对应关系,还是继续抽函数,抽出来每个条件的函数:
# 定义各种函数 def is_a(): return 'A' def is_b(): return 'B' def is_c(): return 'C' def is_d(): return 'D' def is_e(): return 'E'
然后代码变成:
def score_to_af2(score): # 分数除以10以后向下取整,算是属于几十分 score_div_ten = math.floor(score / 10) if 9 <= score_div_ten <= 10: result = is_a() elif score_div_ten == 8: result = is_b() elif score_div_ten == 7: result = is_c() elif score_div_ten == 6: result = is_d() else: result = is_e() return result
条件和执行逻辑&Key和Value
执行逻辑抽取完成,开始抽条件;因为条件和函数对应的关系就是字典中key和value的关系,所以可以抽成一个key是条件,value是函数的字典
# 定义switch-case跳转表,这里90分及以上是A,80分及以上是B,70分及以上是C,60分及以上是D,60分以下都是E(default) switch_dict = { 10: is_a, 9: is_a, 8: is_b, 7: is_c, 6: is_d, }
抽完字典开始围绕字典写逻辑,和上面score_to_af的代码一致,以及最后成品代码也是一致,不再赘述。