Search code examples
pythonfunctionpython-decorators

How to use multiple decorator to a function and chain them together?


How can I make two decorators in Python that would do the following?

@check_zero_error
@check_numerator
def division(a, b):
    return a/b

'check_numerator' will reverse the numbers in case numerator is lesser than denominator.

'check_zero_error' will give check for the zero division error.

The expected output is:

division(1, 2)   # Output : 2.0

division(0, 2)   # Output : "Denominator can't be zero"
 
division(4, 1)   # Output : 4.0

division(5, 0)   # Output : "Denominator can't be zero"

My code is as below but I am not getting expected results:

def check_zero_error(division_func):
    def inner(a, b):
        if b == 0:
            return "Denominator can't be zero"
        else:
            division_func(a, b)
    return inner

def check_numerator(division_func):
    def inner(a, b):
        if a < b:
            a, b = b, a
        division_func(a, b)
    return inner


@check_zero_error
@check_numerator
def division(a, b):
    return a/b
       

print(division(1, 2))  # Expected output : 2.0
print(division(0, 2))  # Expected output : "Denominator can't be zero"
print(division(4, 1))  # Expected output : 4.0

Solution

    1. Your decorators method should return the result of the division

      def check_zero_error(division_func):
          def inner(a, b):
              if b == 0:
                  return "Denominator can't be zero"
              else:
                  return division_func(a, b)
          return inner
      
      def check_numerator(division_func):
          def inner(a, b):
              if a < b:
                  a, b = b, a
              return division_func(a, b)
          return inner
      
    2. Change the order of decorators, first swap (check_numerator) then if needed, THEN check the denominator with check_zero_error

      @check_numerator
      @check_zero_error
      def division(a, b):
          return a / b
      

    Giving expected

    print(division(1, 2))  # actual output : 2.0
    print(division(0, 2))  # actual output : "Denominator can't be zero"
    print(division(4, 1))  # actual output : 4.0
    print(division(5, 0))  # actual output :  "Denominator can't be zero"