代码之家  ›  专栏  ›  技术社区  ›  dassouki

简化python代码中的数据结构和条件语句

  •  2
  • dassouki  · 技术社区  · 15 年前

    我想知道是否有任何方法可以简化下面的代码。正如您所看到的,有许多DICT和条件语句被用来清除错误的输入数据。请注意,跳闸率值尚未全部输入,目前仅复制和粘贴DICT

    编辑

    如果您想复制、粘贴和测试此代码,则此代码可以正常工作

    import math
    
    
    # step 1.4 return trip rates
    def trip_rates( population_stratification, analysis_type, low_income, medium_income, high_income ):
      ''' this function returns the proper trip rate tuple to be used based on input 
        data 
        ADPT = Average Daily Person Trips per Household
        pph = person per household
        veh_hh = vehicles per household
        (param_1, param_2): ADPT
      '''
      li = low_income
      mi = medium_income
      hi = high_income
      # table 5 -
      if analysis_type == 1:
        if population_stratification == 1:
          rates = {( li, 1 ):3.6, ( li, 2 ):6.5, ( li, 3 ):9.1, ( li, 4 ):11.5, ( li, 5 ): 13.8,
                   ( mi, 1 ):3.9, ( mi, 2 ):7.3, ( mi, 3 ):10.0, ( mi, 4 ):13.1, ( mi, 5 ): 15.9,
                   ( hi, 1 ):4.5, ( mi, 2 ):9.2, ( mi, 3 ):12.2, ( mi, 4 ):14.8, ( mi, 5 ): 18.2}
          return rates
        if population_stratification == 2:
          rates = {
                   ( li, 1 ):3.1, ( li, 2 ):6.3, ( li, 3 ):9.4, ( li, 4 ):12.5, ( li, 5 ): 14.7,
                   ( mi, 1 ):4.8, ( mi, 2 ):7.2, ( mi, 3 ):10.1, ( mi, 4 ):13.3, ( mi, 5 ): 15.5,
                   ( hi, 1 ):4.9, ( mi, 2 ):7.7, ( mi, 3 ):12.5, ( mi, 4 ):13.8, ( mi, 5 ): 16.7
                  }
          return rates
        if population_stratification == 3: #TODO: input actual rate
          rates = {
                   ( li, 1 ):3.6, ( li, 2 ):6.5, ( li, 3 ):9.1, ( li, 4 ):11.5, ( li, 5 ): 13.8,
                   ( mi, 1 ):3.9, ( mi, 2 ):7.3, ( mi, 3 ):10.0, ( mi, 4 ):13.1, ( mi, 5 ): 15.9,
                   ( hi, 1 ):4.5, ( mi, 2 ):9.2, ( mi, 3 ):12.2, ( mi, 4 ):14.8, ( mi, 5 ): 18.2
                  }
          return rates
        if population_stratification == 4: #TODO: input actual rate
          rates = {
                   ( li, 1 ):3.1, ( li, 2 ):6.3, ( li, 3 ):9.4, ( li, 4 ):12.5, ( li, 5 ): 14.7,
                   ( mi, 1 ):4.8, ( mi, 2 ):7.2, ( mi, 3 ):10.1, ( mi, 4 ):13.3, ( mi, 5 ): 15.5,
                   ( hi, 1 ):4.9, ( mi, 2 ):7.7, ( mi, 3 ):12.5, ( mi, 4 ):13.8, ( mi, 5 ): 16.7
                  }
          return rates
      #table 6
      elif analysis_type == 2:
        if population_stratification == 1: #TODO: Change rates
          rates = {
                   ( 0, 1 ):3.6, ( 0, 2 ):6.5, ( 0, 3 ):9.1, ( 0, 4 ):11.5, ( 0, 5 ): 13.8,
                   ( 1, 1 ):3.9, ( 1, 2 ):7.3, ( 1, 3 ):10.0, ( 1, 4 ):13.1, ( 1, 5 ): 15.9,
                   ( 2, 1 ):4.5, ( 2, 2 ):9.2, ( 2, 3 ):12.2, ( 2, 4 ):14.8, ( 2, 5 ): 18.2,
                   ( 3, 1 ):4.5, ( 3, 2 ):9.2, ( 3, 3 ):12.2, ( 3, 4 ):14.8, ( 3, 5 ): 18.2
                  }
          return rates
        if population_stratification == 2: #TODO: Change rates
          rates = {
                   ( 0, 1 ):3.6, ( 0, 2 ):6.5, ( 0, 3 ):9.1, ( 0, 4 ):11.5, ( 0, 5 ): 13.8,
                   ( 1, 1 ):3.9, ( 1, 2 ):7.3, ( 1, 3 ):10.0, ( 1, 4 ):13.1, ( 1, 5 ): 15.9,
                   ( 2, 1 ):4.5, ( 2, 2 ):9.2, ( 2, 3 ):12.2, ( 2, 4 ):14.8, ( 2, 5 ): 18.2,
                   ( 3, 1 ):4.5, ( 3, 2 ):9.2, ( 3, 3 ):12.2, ( 3, 4 ):14.8, ( 3, 5 ): 18.2
                  }
          return rates
        if population_stratification == 3: #TODO: Change rates
          rates = {
                   ( 0, 1 ):3.6, ( 0, 2 ):6.5, ( 0, 3 ):9.1, ( 0, 4 ):11.5, ( 0, 5 ): 13.8,
                   ( 1, 1 ):3.9, ( 1, 2 ):7.3, ( 1, 3 ):10.0, ( 1, 4 ):13.1, ( 1, 5 ): 15.9,
                   ( 2, 1 ):4.5, ( 2, 2 ):9.2, ( 2, 3 ):12.2, ( 2, 4 ):14.8, ( 2, 5 ): 18.2,
                   ( 3, 1 ):4.5, ( 3, 2 ):9.2, ( 3, 3 ):12.2, ( 3, 4 ):14.8, ( 3, 5 ): 18.2
                  }
          return rates
        if population_stratification == 4: #TODO: Change rates
          rates = {
                   ( 0, 1 ):3.6, ( 0, 2 ):6.5, ( 0, 3 ):9.1, ( 0, 4 ):11.5, ( 0, 5 ): 13.8,
                   ( 1, 1 ):3.9, ( 1, 2 ):7.3, ( 1, 3 ):10.0, ( 1, 4 ):13.1, ( 1, 5 ): 15.9,
                   ( 2, 1 ):4.5, ( 2, 2 ):9.2, ( 2, 3 ):12.2, ( 2, 4 ):14.8, ( 2, 5 ): 18.2,
                   ( 3, 1 ):4.5, ( 3, 2 ):9.2, ( 3, 3 ):12.2, ( 3, 4 ):14.8, ( 3, 5 ): 18.2
                  }
          return rates
      # table 7
      elif analysis_type == 3:
        if population_stratification == 1: #TODO: input actual rate
          rates = {
                   ( li, 0 ):3.6, ( li, 1 ):6.5, ( li, 2 ):9.1, ( li, 3 ):11.5,
                   ( mi, 0 ):3.9, ( mi, 1 ):7.3, ( mi, 2 ):10.0, ( mi, 3 ):13.1,
                   ( hi, 0 ):4.5, ( mi, 1 ):9.2, ( mi, 2 ):12.2, ( mi, 3 ):14.8
                  }
          return rates
        if population_stratification == 2: #TODO: input actual rate
          rates = {
                   ( li, 0 ):3.6, ( li, 1 ):6.5, ( li, 2 ):9.1, ( li, 3 ):11.5,
                   ( mi, 0 ):3.9, ( mi, 1 ):7.3, ( mi, 2 ):10.0, ( mi, 3 ):13.1,
                   ( hi, 0 ):4.5, ( mi, 1 ):9.2, ( mi, 2 ):12.2, ( mi, 3 ):14.8
                  }
          return rates
        if population_stratification == 3: #TODO: input actual rate
          rates = {
                   ( li, 0 ):3.6, ( li, 1 ):6.5, ( li, 2 ):9.1, ( li, 3 ):11.5,
                   ( mi, 0 ):3.9, ( mi, 1 ):7.3, ( mi, 2 ):10.0, ( mi, 3 ):13.1,
                   ( hi, 0 ):4.5, ( mi, 1 ):9.2, ( mi, 2 ):12.2, ( mi, 3 ):14.8
                  }
          return rates
        if population_stratification == 4: #TODO: input actual rate
          rates = {
                   ( li, 0 ):3.6, ( li, 1 ):6.5, ( li, 2 ):9.1, ( li, 3 ):11.5,
                   ( mi, 0 ):3.9, ( mi, 1 ):7.3, ( mi, 2 ):10.0, ( mi, 3 ):13.1,
                   ( hi, 0 ):4.5, ( mi, 1 ):9.2, ( mi, 2 ):12.2, ( mi, 3 ):14.8
                  }
          return rates
    
    def interpolate( population_stratification, analysis_type, low_income, medium_income, high_income, x, y ):
      #get rates dict
      rates = trip_rates( population_stratification, analysis_type, low_income, medium_income, high_income )
    
    
      # dealing with x parameters
      #when using income levels, x_1 and x_2 are li, mi, or hi
      if analysis_type == 1 or analysis_type == 2 or analsis_type == 4:
        if x < high_income and x >= medium_income:
          x_1 = medium_income
          x_2 = high_income
        elif x < medium_income:
          x_1 = low_income
          x_2 = medium_income
        else:
          x_1 = high_income
          x_2 = high_income
      if analysis_type == 3:
        if x >= 3:
          x_1 = 3
          x_2 = 3
        else:
          x_1 = int( math.floor( x ) )
          x_2 = int( math.ceil( x ) )
    
      # dealing with y parametrs
      #when using persons per household, max number y = 5
      if analysis_type == 1 or analysis_type == 4:
        if y >= 5:
          y_1 = 5
          y_2 = 5
        else:
          y_1 = int( math.floor( y ) )
          y_2 = int( math.ceil( y ) )
      elif analysis_type == 2 or analysis_type == 3:
        if y >= 5:
          y_1 = 5
          y_2 = 5
        else:
          y_1 = int( math.floor( y ) )
          y_2 = int( math.ceil( y ) )
    
      # denominator
      z = ( ( x_2 - x_1 ) * ( y_2 - y_1 ) )
    
      result = ( ( ( rates[( x_1, y_1 )] ) * ( ( x_2 - x ) * ( y_2 - y ) ) / ( z ) ) +
                 ( ( rates[( x_2, y_1 )] ) * ( ( x - x_1 ) * ( y_2 - y ) ) / ( z ) ) +
                 ( ( rates[( x_1, y_2 )] ) * ( ( x_2 - x ) * ( y - y_1 ) ) / ( z ) ) +
                 ( ( rates[( x_2, y_2 )] ) * ( ( x - x_1 ) * ( y - y_1 ) ) / ( z ) ) )
    
      return result
    
    #test
    low_income = 20000 #this is calculated using exchange rates
    medium_income = 40000 # this is calculated using exchange rates
    high_income = 60000 # this is calculated using exchange rates
    population_stratification = 1 #inputed by user
    analysis_type = 1 #inputed by user
    x = 35234.34 #test income
    y = 3.5 # test pph
    
    print interpolate( population_stratification, analysis_type, low_income, medium_income, high_income, x, y )
    
    2 回复  |  直到 15 年前
        1
  •  5
  •   BenMorel Manish Pradhan    11 年前

    那么,从哪里开始呢?这只是第一个观察结果:

    这里有很多数据,代码和数据似乎是相互混合的。

    数据和代码应该分开。数据是一个外部源,您可以修改或读取它。您可能需要修改代码,以便将数据从良好的可编辑表示快速解析为对算法有用的表示。我怀疑您的代码会更短、更清晰、更不容易出错(您是否注意到所有的“rates”字典都有多个键,并且您错过了很多“hi”键?)。

    如果您需要更好的抽象,如矩阵和数据数组,请查看 numpy


    你数过你的尺寸了吗?这里有一个具有X维的多维矩阵: 分析类型、人口分层、收入水平、指数


    编辑2

    好的,我将介绍一些较小的python风格:测试集合或范围中的值。

    if analysis_type == 1 or analysis_type == 2 or analsis_type == 4:
    

    你可以用

    if analysis_type in (1, 2, 4):
    

    或者甚至使用可读的名称,如建议的那样(立方,…)。

    而不是:

    if x < high_income and x >= medium_income:
    

    您可以使用链接条件;Python是为数不多的编程语言之一,其中条件链生成nautral if语句:

    if medium_income <= x < high_income:
    

    当然,比小代码量更重要的是代码设计和重构。编辑2只能给你一些润色。

    你应该学会厌恶重复的代码。

    analysis_type

    你明白你的职能吗 trip_rates 可以这样实施吗?可能吗?

    data_model = compute_table(low_income, ...)
    return data_model[analysis_type][population_stratification]
    
        2
  •  2
  •   Kathy Van Stone    15 年前

    除了kaizer关于数据和代码的建议外,下面是一些简单的清理:

    if y >= 5:
          y_1 = 5
          y_2 = 5
        else:
          y_1 = int( math.floor( y ) )
          y_2 = int( math.ceil( y ) )
    

    可以写成

    min(5, int(math.floor(y))
    

    int(math.floor(min(5, y))
    

    甚至做了一个功能:

    def limitedInt(v, maxV):
       return min(5, int(math.floor(y))
    

    我也建议你这样做,而不是说 analysis_type == 1 你说什么 analysis_type = CUBIC

    你可能会找到这本书 Refactoring Refactoring Workbook the website 也可以使用,但是如果不知道书中描述的“代码气味”,它就没有那么大的帮助。