if-else链是否有更短的方式?

时间:2017-11-15 06:11:47

标签: python python-3.x

if (80 <= m <= 100):
    g = "A"
elif (70 <= m < 80):
    g = "B"
elif (60 <= m < 70):
    g = "C"
elif (50 <= m < 60):
    g = "D"
elif (m < 50):
    g = "U"

这基本上是一个等级测量代码,它接受值m,意思是标记,并获得等级g。为了同样的目的,是否有更短的不一定更多的pythonic方式?

提前致谢。

9 个答案:

答案 0 :(得分:7)

首先,您可以通过删除其中一个边界来简化:

if m >= 80:
    g = "A"
elif m >= 70:
    g = "B"
elif m >= 60:
    g = "C"
elif m >= 50:
    g = "D"
else:  # default catch-all
    g = "U"

其次,您可以通过循环捕获进程的重复性(默认情况下为for-else构造提供选项):

# iterator: ('A', 80) -> ('B', 70) -> ...
for grade, score in zip('ABCD', (80, 70, 60, 50)):
    if m >= score:
        g = grade
        break
else:  # executed if for-loop isn't 'break'-ed out of
    g = 'U'

答案 1 :(得分:4)

是的,你可以这样做,但它不会减少代码:

if m < 50:
    g = "U"
elif m < 60:
    g = "D"
elif m < 70:
    g = "C"
elif m < 80:
    g = "B"
else:
    g = 'A'

作为单线(难以阅读):

g = 'U' if m < 50 else "D" if m < 60 else "C" if m < 70 else "B" if m < 80 else "A"

答案 2 :(得分:4)

更短,更少Pythonic?肯定:

g='UUUUUDCBAAA'[int(m)//10]

实际上,我认为您的代码很好地传达了它的意图并且易于阅读。大多数其他解决方案都不会。

您也可以这样做:

GRADES = {
    'A': (80, float('+inf')),
    'B': (70,  80),
    'C': (60,  70),
    'D': (50,  60),
    'U': ( 0,  50),
}

def letter_grade(points):
    return next(g for g, (start, end) in GRADES.items() if start <= points < end)

我认为这很简单,可以通过首次阅读(虽然我可能有偏见)

答案 3 :(得分:2)

如果numpy可以接受,则会searchsorted。免费奖金:它可以一次性处理整个标记列表:

import numpy as np

bnds = np.arange(50, 90, 10)
grades = np.array(list('UDCBA'))

marks = [52, 16, 50, 80, 69, 99]

result = grades[np.searchsorted(bnds, marks, side='right')]

print(result)

# ['D' 'U' 'D' 'A' 'C' 'A']

答案 4 :(得分:1)

我将利用单个答案和触摸范围来减少比较次数,但也使用元组解包来表达查找表的结构。

if m <= 100:
    g = next(grade for grade, belowscore in
           (('U',50), ('D',60), ('C',70), ('B',80), ('A',100+1))
           if m < belowscore)

这使用生成器表达式来处理类似测试的列表,通过只读取一个结果来进行快捷方式。这受到LISP's conditional operation的启发。 Haskell在模式保护中也有类似的东西。

答案 5 :(得分:0)

这是另一个变种,除了已发布的许多变种:

marks = [0, 50, 60, 70, 80, 100]
grades = ["U", "D", "C", "B", "A"]
g = [grades[i] for i in range(len(grades)) if ((m >= marks[i]) and (m < marks[i+1])) ][0]

当前学生的分数在m,分数在g

答案 6 :(得分:0)

不要改变你的代码。它易读且易于维护。

一般来说,跳过&#34; smart&#34;单行,因为编译器/口译员可以轻松理解您的代码,但人类可能很难理解它。

答案 7 :(得分:0)

使用pandas.cut

import numpy as np
import pandas as pd

bins = [-np.inf, 50, 60, 70, 80, 100]
labels=list('UDCBA')
print(pd.cut(pd.Series(m), bins=bins, labels=labels).iat[0])
# D

如果您有多个成绩,这尤其适用:

grades = np.random.randint(low=45, high=99, size=5)  # 5 grades

print(pd.cut(pd.Series(grades), bins=bins, labels=labels).tolist())
# ['U', 'C', 'A', 'A', 'A']

答案 8 :(得分:0)

使用字典,

m = int(input("Enter Marks:"))

a = {'A' : 80 <= m <= 100, 'B' : 70 <= m < 80, 'C' : 60 <= m < 70, 'D' : 50 <= m < 60, 'U' : m<50}

for key, value in a.items():
    if value == True:
        print(key)

给予

Enter Marks:35
U

[Program finished]

如果你想在多个条目上运行这个,我建议切换到一个函数,该函数返回你传入的任何值的字母等级。