简体   繁体   中英

Python comparison

Is there a more elegant way to make this comparison? I cant imagine, check if received value is > or < .

range_1 = 1000

percent_1 = 10

range_2 = 1500

percent_2 = 15

range_3 = 1500.01

percent_3 = 20
class UtilsPurchase:
    @classmethod
    def calculate_cashback(cls, purchase_value):

        if purchase_value <= range_1:
            result = D(purchase_value / 100) * D(percent_1)
            return {'percent': percent_1, 'calculated_value': D(result)}

        if range_1 < purchase_value <= range_2:
            result = D(purchase_value / 100) * D(percent_2)
            return {'percent': percent_2, 'calculated_value': D(result)}

        if purchase_value >= range_3:
            result = D(purchase_value / 100) * D(percent_3)
            return {'percent': percent_3, 'calculated_value': D(result)}

I would suggest using if , elif , and else statements to combine the three separate if statements into one conditional statement.

For instance:

if purchase_value <= range_1:
    result = D(purchase_value / 100) * D(percent_1)
    return {'percent': percent_1, 'calculated_value': D(result)}

elif purchase_value <= range_2:
    result = D(purchase_value / 100) * D(percent_2)
    return {'percent': percent_2, 'calculated_value': D(result)}

else:
    result = D(purchase_value / 100) * D(percent_3)
    return {'percent': percent_3, 'calculated_value': D(result)}

This would also solve the issue of your code not being able to perform calculations on a purchase_value that is between 1500 and 1500.01 (with the above code it would go into the else section).

You can simplify your code by putting everything you repeat into a function:

class UtilsPurchase:
    @classmethod
    def calculate_cashback(cls, purchase_value):
        if purchase_value <= range_1:
            return cashback_helper(purchase_value, percent_1)

        elif purchase_value <= range_2:
            return cashback_helper(purchase_value, percent_2)

        elif purchase_value >= range_3:
            return cashback_helper(purchase_value, percent_3)


    def cashback_helper(purchase_value, percent):
        result = D(purchase_value / 100) * D(percent)
        return {'percent': percent, 'calculated_value': D(result)}

This is pretty close to a text-book use case for the bisect module from the standard Python library. See the first example in the documentation . You can give the the breakpoints, the purchase_value s and a particular value, it will tell what index you need, which you can use to find the percent you are interested in.

You haven't told us what D() does so I'm just using an identity function:

from bisect import bisect 

def D(v):
    return v

class UtilsPurchase:
    ranges = [1000, 1500]
    percents = [10, 15, 20]

    @classmethod
    def calculate_cashback(cls, purchase_value):
        percent = percents[bisect(ranges, purchase_value)]
        result = D(purchase_value / 100) * D(percent)
        return {'percent': percent, 'calculated_value': D(result)}

UtilsPurchase.calculate_cashback(1100)
# {'percent': 15, 'calculated_value': 165.0}

UtilsPurchase.calculate_cashback(5)
# {'percent': 10, 'calculated_value': 0.5}

This makes it easy to add more breakpoints without strings of if/elif blocks.

This may reduce lines of code and avoid extra checking:

def GetFormattedResult(percent, purchase_value):
    result = D(purchase_value / 100) * D(percent)
    return {'percent': percent, 'calculated_value': D(result)}

class UtilsPurchase:
    @classmethod
    def calculate_cashback(cls, purchase_value):

        if purchase_value <= range_1:
            GetFormattedResult(purchase_value, range_1)

        elif range_1 < purchase_value <= range_2:
            GetFormattedResult(purchase_value, range_2)

        else: purchase_value >= range_3:
            GetFormattedResult(purchase_value, range_3)

It's always best to minimize duplicated code. You can see all 3 of your if statements are almost entirely the same.

cutoffs = [1000, 1500, float("inf")]
percentages = [10, 15, 20]

for cutoff, percentage in zip(cutoffs, percentages):
    if purchase_value <= cutoff:
        result = D(purchase_value / 100) * D(percentage)
        return {'percent': percentage, 'calculated_value': D(result)}

You could try something like this:


def calculate_cashback(purchase_value):
    values=[1000,1500]
    cashback=[0.10,0.15,20]
    c = 0
    for(i,t in enumerate(values)):
        if purchase_value > t:
            c = i+1
        else
            break
    
    return {'percent':cashback[c]*100,'calculated_value':purchase_value*(1-cashback[c]) }

Note, 'percent' will be return as a full integer and not a decimal. You can change it according to your needs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM