【问题标题】:shortening many if-elifs? funcitions in dictionary?缩短许多 if-elif?字典中的函数?
【发布时间】:2021-07-01 04:19:38
【问题描述】:

由于我在比较温度以确定温度的形容词时遇到了许多丑陋的 if-elif,我想我可以在字典的列表中查找温度值,其中它的键将是对应的形容词温度:

def deternmine_temp(temp):

temps = {
    'FREEZING'  : [i for i in range(-20, 0)],
    'very cold' : [i for i in range(0, 6)],
    'cold'      : [i for i in range(6, 11)],
    'chilly'    : [i for i in range(11, 16)],
    'cool'      : [i for i in range(16, 21)],
    'warm'      : [i for i in range(21, 26)],
    'hot'       : [i for i in range(26, 31)],
    'very hot'  : [i for i in range(31, 36)],
    'dangerously hot' : [i for i in range(36, 40)],
    'extremely dangerously hot': [i for i in range(41, 46)]
}

temp = int(temp.replace('°', '').strip())

for word, values in temps.items():
    if temp in values:
        return word

这比 7+ if-elif 好很多,但我认为它不是很有效,尤其是在 temps 有更多数据的情况下(例如,如果我对应于形容词的值范围更窄)。

有什么方法可以提高效率?也许字典中有一些功能?以上真的是我能想到的最好的了。

【问题讨论】:

标签: python python-3.x


【解决方案1】:

您需要以某种方式存储范围,并且由于范围没有相同的间隔,您不能真正缩短字典初始化。您可以将字典创建提取到一个函数中,但是您仍然需要尽可能多地调用它。

但是,您可以从字典中删除列表推导,并将循环替换为 next

def deternmine_temp(temp):
    temps = {
            'FREEZING': range(-20, 0),
            'very cold': range(0, 6),
            'cold': range(6, 11),
            'chilly': range(11, 16),
            'cool': range(16, 21),
            'warm': range(21, 26),
            'hot': range(26, 31),
            'very hot': range(31, 36),
            'dangerously hot': range(36, 40),
            'extremely dangerously hot': range(41, 46)
            }

    temp = int(temp.replace('°', '').strip())
    return next((word for word, values in temps.items() if temp in values), None)

【讨论】:

    【解决方案2】:

    如果您决定将温度表示为浮点数,您的代码通常将无法工作。为确保您的代码适用于非整数温度(以防万一),请将范围表示为成对的最小值-最大值并使用显式比较:

    temps = {
        'FREEZING'  : (-20, 0),
        'very cold' : (0, 6),
        ....
    }
    
    for word, values in temps.items():
        if values[0] <= temp < values[1]:
            return word
    

    您也可以使用元组列表,因为您不使用特定于字典的功能:

    temps = [
        ('FREEZING', -20, 0),
        ('very cold', 0, 6),
        ....
    ]
    
    for word, value1, value2 in temps:
        if value1 <= temp < values2:
            return word
    

    最后,为了一致性,你可以只定义范围的上边界(同时也是下一个范围的下边界):

    temps = [
        ('FREEZING', 0),
        ('very cold', 6),
        ....
        ('extremely dangerously hot': float('inf'))
    ]
    
    for word, value in temps:
        if temp < value:
            return word
    

    【讨论】:

      【解决方案3】:

      This 最接近我想要的。

      def switch(x):
          return {
                  -20<x<=2: 'FREEZING',
                  2<x<=5: 'very cold',
                  5<x<=10: 'cold',
                  10<x<=15: 'chilly',
                  15<x<=22: 'cool',
                  22<x<=25: 'warm',
                  25<x<=30: 'hot',
                  30<x<=33: 'very hot',
                  33<x<=35: 'extremely hot',
                  35<x<=40: 'dangerously hot'
                  }[1]
      
      print(switch(40))
      

      输出:

      dangerously hot
      

      【讨论】:

      • 这很有趣。我以前没有见过这种语法。它是如何工作的?大括号 {} 中的部分是字典吗?如果是这样,这是一个奇怪的字典,其中的键将是布尔值。这甚至是一件事吗?
      • 哦。我有点想通了。所有键都将评估为 True 或 False,即 1 或 0。因此,当调用函数时,您会得到一个包含许多 False (0) 键和一个 True (1) 键的字典。在此函数中,您可以将 [1] 替换为 [True] 并获得相同的结果。有趣....
      • 对,我也没有。以前从未见过,但看起来最接近我想要的。
      • FWIW,Python 3.10 应该内置了 switch case 语句。只有它会被称为 match case,完整的正式名称是 Structural Pattern Matching。
      猜你喜欢
      • 1970-01-01
      • 2022-11-23
      • 2022-06-19
      • 1970-01-01
      • 2019-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-31
      相关资源
      最近更新 更多