【问题标题】:Reducing the use of if's / elif [closed]减少使用 if's / elif [关闭]
【发布时间】:2020-11-07 19:44:56
【问题描述】:

在执行列表/字典/元组的代码中,有什么方法可以减少 if 和 elif 的数量?

cod =
    ['menu'],
    ['dimension 1"'],
    ['dimension 2”'],
    ['dimension 3”'],
    ['dimension 4'],
    ['dimension 5'],
    ['dimension 6'],
    ['dimension 7'],
    ['dimension 8'],
    ['dimension 9'],
    ['dimension 10']
]
return cod

    if choice == 1:
    quantify = float(input(('Quantify: ')))
    if 0 < quantify <= 6:
        print('± 0,1mm')
    elif 6 < quantify <= 30:
        print('± 0,2mm')
    elif 30 < quantify <= 120:
        print('± 0,3mm')
    elif 120 < quantify <= 400:
        print('± 0,5mm')
    elif 400 < quantify <= 1000:
        print('± 0,8mm')
    elif 1000 < quantify <= 2000:
        print('± 1,2mm')
    elif 2000 < quantify <= 4000:
        print('± 2mm')
    else:
        print('<<< Min = 0,5mm | Max = 4000mm >>>')
elif choice == 2:
    quantify = float(input(('Quantify: ')))
    if 0 < quantify <= 3:
        print('± 0,2mm')
    elif 3 < quantify <= 6:
        print('± 0,5mm')
    elif 6 < quantify:
        print('± 1mm')
    else:
        print('<<< Min = 0,5mm | Max = ∞ >>>')

*我必须更改一些内容以使其可读,因为它是葡萄牙语和其他一些功能。

谢谢, 出售卡瓦略

【问题讨论】:

标签: python list dictionary if-statement simplify


【解决方案1】:

您使用字典和列表的想法是正确的。这就是我简化您的代码以不使用一堆 if else 语句的方式。

from collections import namedtuple

tolerance = namedtuple( 'tolerance', ['lower_bound', 'upper_bound', 'tolerance'] )

tolerances = {
    '1': [
        tolerance(0, 6, '± 0,1mm'),
        tolerance(6, 30, '± 0,2mm'),
        tolerance(30, 120, '± 0,3mm'),
        tolerance(120, 400, '± 0,5mm'),
        tolerance(400, 1000, '± 0,8mm'),
        tolerance(1000, 2000, '± 1,2mm'),
        tolerance(2000, 4000, '± 2mm')
    ],
    '2': [
        tolerance(0, 3, '± 0,2mm'),
        tolerance(3, 6, '± 0,5mm'),
        tolerance(6, 'inf', '± 1mm'),
    ]
}

def get_tolerance(quantify, choice):
    for t in tolerances[choice]:
        if t.lower_bound <= quantify <= t.upper_bound:
            return t.tolerance

    # if we didn't find a matching tolerance, raise an error
    min_tolerance = min( t.lower_bound for t in tolerances[choice] )
    max_tolerance = max( t.lower_bound for t in tolerances[choice] )
    raise ValueError(f'<<< Min = {min_tolerance} | Max = {max_tolerance} >>>')


choice = input('Choice: ')
while choice not in tolerances:
    print('Invalid choice. Choice must be one of the following:', ', '.join(tolerances.keys()))
    choice = input('Choice: ')

quantify = float(input('Quantify: '))
print('Tolerance is:', get_tolerance(quantify, choice))

我选择使用称为named tuple 的东西而不是列表来存储公差信息。如果您从未听说过命名元组,它们的工作方式是您指定一些字段(例如,lower_bound、upper_bound、tolerance),然后您会返回在我们的例子中是一个tolerance,您可以使用它来创建命名元组.当我们使用tolerance 创建一个命名元组时,例如t = tolerance(0, 6, '± 0,1mm'),那么我们可以使用t.lower_bound 获得下限,t.upper_bound 获得上限,t.tolerance。当您需要存储固定数量的项目时,使用这样的命名元组而不是列表可以使代码更易于阅读。

【讨论】:

    【解决方案2】:

    替换包含严格相等比较的if...elif 链非常简单。但是,当您有一个范围时,字典不是正确的解决方案。相反,您将需要一个自定义数据结构,该结构将每个范围的开头和结尾与 if 语句进行比较。然后,您可以使用 for 循环遍历范围列表中的所有范围。

    【讨论】:

      【解决方案3】:

      这里有两种方法。注意到其他人也发布了类似的内容:)

      """ SO QA """
      
      import bisect
      
      
      class Tolerance:
          def __init__(self, lower_limit, text):
              self._lower_limit = lower_limit
              self._text = text
      
          def __eq__(self, other):
              return self.lower_limit == other.lower_limit
      
          def __lt__(self, other):
              return self.lower_limit < other.lower_limit
      
          def __gt__(self, other):
              return self.lower_limit > other.lower_limit
      
          def __str__(self):
              return '{:4d} {}'.format(self.lower_limit, self.text)
      
          @property
          def lower_limit(self):
              return self._lower_limit
      
          @property
          def text(self):
              return self._text
      
          @staticmethod
          def get(tolerance_list, value):
              if isinstance(value, int):
                  value = Tolerance(value, "")
              if isinstance(value, Tolerance):
                  idx = bisect.bisect_right(tolerance_list, value)
                  if idx:
                      return tolerance_list[idx-1]
                  raise ValueError('value {} is out of range'.format(value))
              raise TypeError('unexpected type: {}'.format(type(value)))
      
      
      _TOLERANCES = [
          Tolerance(   0, '± 0,1mm'),
          Tolerance(   6, '± 0,2mm'),
          Tolerance(  30, '± 0,3mm'),
          Tolerance( 120, '± 0,5mm'),
          Tolerance( 400, '± 0,8mm'),
          Tolerance(1000, '± 1,2mm'),
          Tolerance(2000, '± 2,0mm'),
          Tolerance(4000, 'over range'),
      ]
      
      
      def get_tolerance_using_dict(value):
          """
          Based on the value, get the tolerance entry.
          :param value: The integer value that is within the expected range.
          :returns:     A entry dict {lower_limit: value, text: ""}.
          """
          tolerances = [
              {'lower_limit':    0, 'text': '± 0,1mm'},
              {'lower_limit':    6, 'text': '± 0,2mm'},
              {'lower_limit':   30, 'text': '± 0,3mm'},
              {'lower_limit':  120, 'text': '± 0,5mm'},
              {'lower_limit':  400, 'text': '± 0,8mm'},
              {'lower_limit': 1000, 'text': '± 1,2mm'},
              {'lower_limit': 2000, 'text': '± 2,0mm'},
              {'lower_limit': 4000, 'text': 'over range'},
          ]
      
          prev_entry = None
          for entry in tolerances:
              if entry['lower_limit'] <= value:
                  prev_entry = entry
              else:
                  return prev_entry
          return tolerances[len(tolerances) - 1]
          # Perhaps a better way to handle the range error:
          # raise ValueError('value is out of range'.format(value))
      
      
      def main():
          """ Test the stuff """
          values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 29, 30, 100, 119, 120, 121,
                    1999, 2000, 2001, 3999, 4000, 4001]
      
          print('using class:')
          for value in values:
              print('{:3} : {}'.format(value, Tolerance.get(_TOLERANCES, value)))
      
          print('using dict:')
          for value in values:
              print('{:3} : {}'.format(value, get_tolerance_using_dict(value)))
      
      
      
      if __name__ == "__main__":
          main()
      

      【讨论】:

      • 非常感谢。我会尝试该代码,但我无法理解其中的大部分内容,因为我还没有学会如何使用类。所以,我在理解代码方面有点困难。但我会一直保留到有一天我理解它时可以使用它。再次感谢 Natersoz。
      猜你喜欢
      • 2017-12-27
      • 2022-01-22
      • 2021-06-10
      • 2016-06-30
      • 1970-01-01
      • 1970-01-01
      • 2022-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多