【问题标题】:Refactoring multiple if / elif statements including inequalities重构多个 if / elif 语句,包括不等式
【发布时间】:2021-06-18 15:14:52
【问题描述】:

我想用更 Python 的东西(最好是设计模式)替换多个 if/elif 语句:

def calculate_coords(self, num_of_chars):
    if num_of_chars <  20:
        return int(num_of_chars * 6.8 )
    elif num_of_chars <  30:
        return int(num_of_chars * 6.7 )
    elif num_of_chars <  40:
        return int(num_of_chars * 6.25 )
    elif num_of_chars <  50:
        return int(num_of_chars * 6.35 )
    elif num_of_chars <  60:
        return int(num_of_chars * 6.2 )
    elif num_of_chars <  70:
        return int(num_of_chars * 6.15 )
    elif num_of_chars <  80:
        return int(num_of_chars * 6.2 )
    elif num_of_chars <  90:
        return int(num_of_chars * 6.05 )
    elif num_of_chars <  100:
        return int(num_of_chars * 6.05 )
    elif num_of_chars <  110:
        return int(num_of_chars * 6)
    elif num_of_chars <  120:
        return int(num_of_chars * 5.9 )
    elif num_of_chars <  130:
        return int(num_of_chars * 5.85 )
    else:
        return int(num_of_chars * 5.85 )

【问题讨论】:

    标签: python design-patterns refactoring


    【解决方案1】:
    def calculate_coords(self, num_of_chars):
        factors = [6.8, 6.7, 6.25, 6.35, 6.2, 6.15, 6.2, 6.05, 6.05, 6, 5.9, 5.85]
        comparison = 20
        for i in range(12):
            comparison += i * 10
            if num_chars < comparison:
                return int(num_chars * factors[i])
        return int(num_of_chars * 5.86)
    

    【讨论】:

      【解决方案2】:

      第一步是设置一个变量来表示应该乘以多少硬币,然后在最后写下乘法一次

      def calculate_coords(self, num_of_chars):
          if num_of_chars < 20:
              x = 6.8
          elif num_of_chars < 30:
              x = 6.7
          ...
          else:
              x = 5.85
          return int(num_of_chars * x)
      

      除此之外,没有什么可以使用原生 Python 进行重构了。您可以使用interval tree 来查找x 的正确值,但这可能不值得。

      鉴于每个阈值仅比前一个高 10,我们可以计算一个列表的索引:

      def calculate_coords(self, num_of_chars):
          amounts = [6.8, 6.7, ..., 5.85]
          i = (num_of_chars - 20) // 10
          try:
              x = amounts[i]
          except IndexError:
              x = 5.85
          return int(num_of_chars * x)
      

      但这可能不如明确列举选择那么清楚。

      【讨论】:

        【解决方案3】:

        我提出了一种基于字典的方法:

        COORDINATES = {
            20: 6.8,
            30: 6.7,
            # ... etc.
        }
        
        def calculate_coords(self, num_of_chars):
            nearest_ten = round(num_of_chars / 10) * 10
            if nearest_ten in COORDINATES:
                return int(num_of_chars * COORDINATES[nearest_ten])
            return num_of_chars * 5.85
        

        【讨论】:

          【解决方案4】:

          也许不是很直观,但如果你稍微弄清楚数学,这很有效:

          def calculate_coords(num_of_chars):
              l = [6.8, 6.8, 6.7, 6.25, 6.35, 6.2, 6.15, 6.2, 6.05, 6.05, 6, 5.9, 5.85]
              return int(num_of_chars*l[min(num_of_chars//10, 12)])
          

          列表l 包含小于[10, 20, 30, 40...130]num_of_chars 的乘法因子。

          num_of_chars 大于 130 时,min() 函数返回 l[12]

          【讨论】:

            【解决方案5】:

            全新的 Python 3.10 加入了这个特性,使用了“match”和“case”。

            文档: Simple pattern: match to a literal

            http_code = "418"
            
            match http_code:
                case "200":
                    print("OK")
                case "404":
                    print("Not Found")
                case "418":
                    print("I'm a teapot")
                case _:
                    print("Code not found")
            

            【讨论】:

            • 你要匹配什么?条件是不等式,而不是等式。
            • @chepner 提到我的“主要问题”是不平等!
            猜你喜欢
            • 2012-09-02
            • 1970-01-01
            • 1970-01-01
            • 2017-07-03
            • 1970-01-01
            • 2017-12-12
            • 1970-01-01
            • 1970-01-01
            • 2016-02-19
            相关资源
            最近更新 更多