我应该使用循环还是坚持使用if嵌套语句?

时间:2019-08-30 19:11:08

标签: python-3.x loops if-statement

我是编程新手。我正在使用python。我正在制定一个程序,该程序将比较本国(巴拉圭)的储蓄帐户的不同利率。由于某些计算在银行中是相似的,但有一些不同,所以我想知道如何更好地构造代码,以免重复。

我应该继续使用if语句吗?有没有办法用循环来做到这一点?我应该怎么想呢?我在下面添加的代码仅适用于一家银行。如果要添加另一个,该如何进行?我的自然倾向会继续if语句:)

PD:如果对我的代码也有任何反馈,我们将不胜感激。或您认为在此阶段可以帮助我的一些资源。请客气,我对这一切仍然没有把握。

def ahorro_cda_nominal_anual (ahorro_inicial, tiempo_en_dias, moneda):

  if moneda == 'dolares':
    if ahorro_inicial>= 5000: 

        if 0 < tiempo_en_dias < 90:
            dMin = 0.05
            dMax = 0.05

        if 90 <= tiempo_en_dias < 180: 
            dMin = 0.15
            dMAx = 0.75

        if 180 <= tiempo_en_dias < 365:
            dMin = 0.25
            dMax = 1.25

        if 365 <= tiempo_en_dias:
            dMin = 1.25
            dMax = 2.00
        monto_final_min = ahorro_inicial * tiempo_en_dias*dMin/365 + ahorro_inicial
        monto_final_max = ahorro_inicial * tiempo_en_dias *dMax/365 + ahorro_inicial
        print ("Obtendrias minimamente " + str(round(monto_final_min/1000,3)) + " mil dolares.")
        print ("Hasta un valor maximo de " + str(round(monto_final_max/1000,3)) + " mil dolares.")
        return (monto_final_min, monto_final_max)

    else:
        print ("El valor minimo es de 5000 dolares. Necesitas " + str(5000 - ahorro_inicial) + " dolares mas.")

  elif moneda == 'guaranies':
    if ahorro_inicial >= 5000000:

        if 0 < tiempo_en_dias < 90:
            gMin = 0.25
            gMax = 2.5

        if 90 <= tiempo_en_dias < 180: 
            gMin = 0.75
            gMax = 2.5

        if 180 <= tiempo_en_dias < 365:
            gMin = 1.0
            gMax = 4.5

        if 365 <= tiempo_en_dias:
            gMin = 1.5
            gMax = 5.5

        monto_final_min = ahorro_inicial * tiempo_en_dias*gMin/365 + ahorro_inicial
        monto_final_max = ahorro_inicial * tiempo_en_dias *gMax/365 + ahorro_inicial
        print ("Obtendras minimamente " + str(round(monto_final_min/1000000,1)) + " milllones de guaranies.")
        print ("Y a lo sumo " + str(round(monto_final_max/1000000,1)) + " millones de guaranies.")
        return (monto_final_min, monto_final_max)

    else:
        print ("El monto minimo es 5 millones de guaranies. Necesitas " + str(5000000 - ahorro_inicial) + " guaranies mas.")
  else:
    print ("Solo aceptamos guaranies o dolares.")

ahorro_cda_nominal_anual (50000000, 180,'guaranies')

3 个答案:

答案 0 :(得分:1)

有多种解决方法...如果您的计算仅因数据(保留率,年等)不同,那么我将根据数据驱动方法提出以上答案之一。

如果您的计算本身大不相同(可能不同的库具有不同的子句),则与其使用一种具有复杂if-logic的方法,不如将其分离为不同的方法并用跳转表进行调用。

>

简单的例子:

#!/usr/bin/env python

def bank_type_1(val1, val2):
    print 'bank type 1 calculations...'


def bank_type_2(val1, val2):
    print 'bank type 2 calculations...'



bank_methods = {
    'bank1': bank_type_1,
    'bank2': bank_type_2,
    'bank1_1': bank_type_1
}

def calculate(bank, val1, val2):
    if bank in bank_methods:
        bank_methods[bank](val1, val2)


if __name__ == '__main__':
    calculate('bank1', 10, 100)
    calculate('bank2', 10, 100)
    calculate('bank1_1', 10, 100)

答案 1 :(得分:0)

肯定有几种方法可以改进代码,从而避免像现在一样重复自己的代码。避免重复是件好事,因为这意味着您不会因为只测试了其他可以正常工作的案例而在一个未检测到的角落案例中出现一些细微的错误。

首先,我建议创建一个数据结构,其中包含确定给定贷款请求的利率所需的所有数据。在当前代码中,这看起来是货币和最低贷款额,然后是不同贷款期限的不同利率。我建议使用以货币为键的字典,其值是2元组min_loan, ratesrates值是duration, min_rate, max_rate三元组的列表。

data = {
    'dolares': (5000, [
        (90, 0.05, 0.05),
        (180, 0.15, 0.75),
        (365, 0.25, 1.25),
        (math.inf, 1.25, 2.00),
    ]),
    # similar rates for 'guaranies' would go here, omitted for brevity
}

def ahorro_cda_nominal_anual(ahorro_inicial, tiempo_en_dias, moneda):
    if moneda not in data:
        raise ValueError("Unknown currency {!r}".format(moneda)) # or whatever error handling you want

    min_loan, rates = data[moneda]
    if ahorro_inicial < min_loan:
        raise ValueError("Loan is too small, minimum is {} {}.".format(min_loan, moneda))

    for duration, dMin, dMax in rates:
        if tiempo_en_dias < duration:
            break # stop looping, keeping dMin and dMax at the current values

    monto_final_min = ahorro_inicial * tiempo_en_dias*dMin/365 + ahorro_inicial
    monto_final_max = ahorro_inicial * tiempo_en_dias*dMax/365 + ahorro_inicial
    return (monto_final_min, monto_final_max)

我省略了当前函数的打印输出,主要是因为原始版本中使用的不同货币之间的格式有所不同(而且我的西班牙语说得不够好,无法解决)。您可以很容易地将其放回去,只要您能提出一些适用于每种货币的一致格式即可。如果通用消息不够好,您可以在数据结构中添加一两个格式字符串,这样通用代码可以在需要的任何地方使用不同的语言。

答案 2 :(得分:0)

假设银行之间的汇率和初始金额仅发生变化,我建议使用一种数据结构,该结构包含所有配置数据(针对每个银行和每种货币)。也许是这样,您可以在其中根据需要添加任意数量的银行和货币:

bank_dict = {
    'bank_1': {
        'USD': {
            'min_amount': 5000,
            'rounding': 3,
            'rates': [
                (0, 0.05, 0.05),
                (90, 0.15, 0.75),
                (180, 0.25, 1.25),
                (365, 1.25, 2.00),
            ],
        },
        'GS': {
            'min_amount': 5000000,
            'rounding': 1,
            'rates': [
                (0, 0.25, 2.50),
                (90, 0.75, 2.50),
                (180, 1.00, 4.50),
                (365, 1.50, 5.50),
            ],
        },
    },
    'bank_2': {
        'EUR': {
            'min_amount': 8000,
            'rounding': 3,
            'rates': [
                (0, 0.05, 0.05),
                (90, 0.15, 0.75),
                (180, 0.25, 1.25),
                (365, 1.25, 2.00),
            ],
        },
    },
}

我建议使用python约定,以在数据异常(例如不存在的银行或货币)的情况下引发错误。代码看起来像这样:

def calculate(bank_id, currency_id, initial_amount, days):
    try:
        bank_data = bank_dict[bank_id]
    except KeyError:
        raise ValueError('bank "{}" does not exist'.format(
            bank_id))

    try:
        currency_data = bank_data[currency_id]
    except KeyError:
        raise ValueError('currency "{}" does not exist for bank "{}"'.format(
            currency_id, bank_id))

    if initial_amount < currency_data['min_amount']:
        raise ValueError('initial amount is {} but should be at least {}'.format(
            initial_amount, currency_data['min_amount']))

    # search for rates
    selected_rate_min = 0
    selected_rate_max = 0
    for rate_days, rate_min, rate_max in currency_data['rates']:
        if days < rate_days:
            # exit loop, because the previous rates should stay as selected rates
            break

        selected_rate_min = rate_min
        selected_rate_max = rate_max

    interest_min = round(
        initial_amount * days * selected_rate_min / 365,
        currency_data['rounding'])
    interest_max = round(
        initial_amount * days * selected_rate_max / 365,
        currency_data['rounding'])

    final_amount_min = initial_amount + interest_min
    final_amount_max = initial_amount + interest_max

    print(
        bank_id, currency_id, initial_amount, days,
        selected_rate_min, final_amount_min,
        selected_rate_max, final_amount_max)

    return final_amount_min, final_amount_max

请注意,当您添加更多银行或货币时,该代码将不会增长(假设所有银行都使用此处实现的相同核心逻辑)。


最后一点:如果需要对货币值进行精确舍入,则应查看Pythons decimal数据类型,而不要使用float(例如0.15float )。