正好在stackoverflow上看到一个问题,挺有启发的,所以分享一下。题目大意是:从A到F共有5个等级,现在要判断某个值(从0到1)属于哪个等级。例如,如果值>=0.9,则属于A;如果值>=0.8,则属于B;等等。如果使用if-elif语句,可能会这样写:ifscr>=0.9:print('A')elifscr>=0.8:print('B')elifscr>=0.7:print('C')elifscr>=0.6:print('D')else:print('F')这种写法有很多重复的花样,不够简洁优雅。有什么更好的写作方式来实现这个目标?这个问题的答案比较多,实现思路也五花八门。我挑几个可读性比较强的:方法一:使用bisect模块(数量可调)方法二:使用zip()和next()方法三:使用字典(只适用于Python3.6以上的有序字典)有几种其他答案,虽然可以达到数值分级的目的,但是可读性差很多,因为要么需要你去计算推理,要么引入额外的变量。有兴趣的可以在这个地址查看所有答案:https://stackoverflow.com/questions/61030617/how-can-i-simplify-repetitive-if-elif-statements看完所有答案后,我觉得还是用bisect的方法更高效优雅,值得高票赞同。下面简单分析一下它的实现过程。Bisect是Python中内置的标准库,实现了二分查找算法。所谓二分查找,又称“BinarySearch”,其基本思想是将有序的n个元素一分为二,然后将要查找的x与中间的元素进行比较,如果x小于中间的元素,将左半部分一分为二,然后将x与其中间元素进行比较,依此类推。这是一个简单的图形化例子:bisect库中的bisect()方法按升序查找元素x的插入点i,使得插入点左边的元素都小于等于x,插入点右边的元素都大于x。与前面的例子相比:frombisectimportbisectdefgrade(score,breakpoints=[60,70,80,90],grades='FDCBA'):i=bisect(breakpoints,score)returngrades[i]可以简化为两部分:bisect([60,70,80,90],score),返回插入点的值。如果分数为59,则计算出的插入点在60的左边,Python列表的索引值从0开始,所以返回的插入点值为0;如果分数为60,则计算出的插入点在60边的右边,即返回索引值为1。'FDCBA'[i],返回索引为i的字符。如果i为0,则得到“F”;如果i为3,则得到“B”……二分查找算法是一种效率更高的算法,时间复杂度为O(logn)。这个题目的搜索范围很小,所以时间效率相差不大。但是它的写法堪称Pythonic,值得借鉴。另外再看前面的方法三(使用字典),可读性很强,就是将scr和字典中的值依次比较(从高到低,即0.9~0.5),所以从而获取对应的键值。(PS:多了一个“E”级,可以去掉)如果Python版本低于3.6,grades.items()会无序,会打乱比较顺序。为了兼容性,可以修改为sorted(grades.items()):这种写法没有引入额外的库,使用的items()和sorted()都是基础知识(相对于方法中的zip()和next二()),简单实用,强烈推荐。总之,重复使用if-elif语句的判断方式很笨拙,必须改进。文中列出的答案是目前比较接受的答案。如果面试官拿来当面试题,我觉得会很有意思:不难,还有发展空间。
