Goodbye if... elif... Easy to take down with Python decorator

Hello, everyone. Today, I read the code of EdgeDB[1] in Github and found that it is dealing with a large number of if elif... Else, skillfully used the decorator. The method is exquisite. Let's share it with you.

Let's see what this method looks like. Suppose we want to make a function to judge the discount that a user can get according to his level. Regular if elif... It's written like this:

def get_discount(level):
    if level == 1:
        "Mass calculation code"
        discount = 0.1
    elif level == 2:
        "Mass calculation code"
        discount = 0.2
    elif level == 3:
        discount = 0.3
    elif level == 4:
        discount = 0.4
    elif level == 5:
        discount = 0.5
    elif level == 6:
        discount = 3 + 2 - 5 * 0.1
    else:
         return 'Grade error'
    return discount

As we all know, such a large number of if elif... The code is ugly and difficult to maintain. And there is a lot of code inside each if. This function will be pulled very long.

Some students know that they can rewrite this too long if judgment with a dictionary:

def parse_level_1():
    "Mass calculation code"
    discount = 0.1
    return discount

def parse_level_2():
    "Mass calculation code"
    discount = 0.2
    return discount

def parse_level_3():
    "Mass calculation code"
    discount = 0.3
    return discount

def parse_level_4():
    "Mass calculation code"
    discount = 0.4
    return discount

def parse_level_5():
    "Mass calculation code"
    discount = 0.5
    return discount

def parse_level_6():
    "Mass calculation code"
    discount = 3 + 2 - 5 * 0.1
    return discount

discount_map = {
 1: parse_level_1,
  2: parse_level_2,
  3: parse_level_3,
  4: parse_level_4,
  5: parse_level_5,
  6: parse_level_6,
}

discount = discount_map.get(level, 'Grade error')

But the method I learned today is simpler than using a dictionary. Let's look at its effect first:

@value_dispatch
def get_discount(level):
    return 'Grade error'

@get_discount.register(1)
def parse_level_1(level):
    "Mass calculation code"
    discount = 0.1
    return discount

@get_discount.register(2)
def parse_level_2(level):
    "Mass calculation code"
    discount = 0.2
    return discount

@get_discount.register(3)
def parse_level_3(level):
    "Mass calculation code"
    discount = 0.3
    return discount

@get_discount.register(4)
def parse_level_4(level):
    "Mass calculation code"
    discount = 0.4
    return discount

@get_discount.register(5)
def parse_level_5(level):
    "Mass calculation code"
    discount = 0.5
    return discount

@get_discount.register(6)
def parse_level_1(level):
    "Mass calculation code"
    discount = 3 + 2 - 5 * 0.1
    return discount


discount = get_discount(3)
print(f'For Level 3 users, the discount is:{discount}')

The operation effect is shown in the figure below:

Writing this way is more intuitive than using a dictionary, and more intuitive than directly using if elif... More concise.

So, this decorator_ How is dispatch implemented? The password is hidden in the source code [2] of the open source project EdgeDB. The core code is only more than 20 lines:

Moreover, it can also implement or query. For example, when the user level is 2 or 3 and the discount is 0.2, the code can be written as:

@get_discount.register(2)
@get_discount.register(3)
def parse_level_2(level):
    "Mass calculation code"
    discount = 0.2
    return discount

The operation effect is shown in the figure below:

This code can only implement equal queries at present. But in fact, as long as the code is slightly modified, we can judge greater than, less than, greater than or equal to, less than or equal to, not equal to, in and so on. If you are interested, please leave a message at the bottom of the article. Tomorrow we will talk about how to transform this code and realize more logical judgment.

reference

[1] EdgeDB: https://github.com/edgedb/edgedb

[2] Source code: https://github.com/edgedb/edged

Finally, I wish you progress every day!! The most important thing to learn Python is mentality. We are bound to encounter many problems in the process of learning. We may not be able to solve them if we want to break our head. This is normal. Don't rush to deny yourself and doubt yourself. If you have difficulties in learning at the beginning and want to find a python learning and communication environment, you can join us, receive learning materials and discuss together.

 

 

Keywords: Python Back-end

Added by nev25 on Thu, 13 Jan 2022 09:50:32 +0200