Python Forum
the order of running code in a decorator function
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
the order of running code in a decorator function
#1
hi
in below code:
# from:https://python.coderz.ir/lessons/l14-recursive-  \
# functions-and-memoization-in-python.html 

def logger(func):
     print('Decorator is created!')
     def func_wrapper(number):
         print(f'New factorial call with parameter: {number}')
         result = func(number)
         print (f'factorial({number}) ==> {result}')
         return result
     return func_wrapper

@logger
def factorial(n):
    if n <= 1:
         return 1
    else:
         return n            #* factorial(n - 1)

def test():
     print("it is a test")

if __name__=="__main__" :
    test() 
    print(f"factoril(5) is : {factorial(5)}")
I ran and debugged the above code in idle.
the order of running lines was: 4,13,14,13,5,6,11,14,20,23,24,21,25,7,8,15,18,9,10 .
the above code is a decorator function. why the order of running lines is as above line? plz, explain.
thanks
Reply
#2
The factorial function is more interesting when it works.
def logger(func): # 1
     print(f"{func.__name__} wrapped by logger.") #2
     def func_wrapper(number): #3
         print(f"{func.__name__}({number})") # 4
         result = func(number) # 5
         print (f'==> {result}') # 6
         return result # 7
     return func_wrapper # 8

print("Decorating factorial") #10
@logger # 11
def factorial(n): # 12
    if n <= 1: # 13
         return 1 # 14
    else: # 15
         return n * factorial(n-1) # 16

print("Using the wrapped function") # 18
print(f"factorial(5) is : {factorial(3)}") # 19
Output:
Decorating factorial factorial wrapped by logger. Using the wrapped function factorial(3) factorial(2) factorial(1) ==> 1 ==> 2 ==> 6
The first two output lines:
Output:
Decorating factorial factorial wrapped by logger.
Show that the logger function gets called when we wrap the factorial function, not when the factorial function gets called at the end of the program.

This code:
@logger # 11
def factorial(n): # 12
replaces "factorial" with "func_wrapper". When the program later calls "factorial(5)" it is really calling "func_wrapper(5)",

The program calls "func_wrapper" here:
print(f"factorial(5) is : {factorial(3)}") # 19
So we begin executing func_wrapper's code.
         print(f"{func.__name__}({number})") # 4
         result = func(number) # 5
         print (f'==> {result}') # 6
         return result # 7
This line:
result = func(number) # 5)
calls "func" which is the original "factorial" function, so we start executing the original factorial function code:
    if n <= 1: # 13
         return 1 # 14
    else: # 15
         return n * factorial(n-1) # 16
When we get to this line:
return n * factorial(n-1) # 16
We recursively call the "factorial" function. But remember, the factorial function has been replaced with a call to "func_wrapper" so we find ourselves here:
         print(f"{func.__name__}({number})") # 4
         result = func(number) # 5
         print (f'==> {result}') # 6
         return result # 7
The end result is that the program lines are executed in this order:
print("Decorating factorial") #10
def logger(func): # 1
     print(f"{func.__name__} wrapped by logger.") #2
     return func_wrapper # 8
print("Using the wrapped function") # 18
factorial(3)
    def func_wrapper(3): #3
         print(f"{func.__name__}({3})") # 4
         result = func(3) # 5
def factorial(3): # 12
    if 3 <= 1: # 13
    else: # 15
         return 3 * factorial(2) # 16
    def func_wrapper(2): #3
         print(f"{func.__name__}({2})") # 4
         result = func(2) # 5
def factorial(2): # 12
    if 2 <= 1: # 13
    else: # 15
         return 2 * factorial(1) # 16
    def func_wrapper(1): #3
         print(f"{func.__name__}({1})") # 4
         result = func(1) # 5
def factorial(1): # 12
    if 1 <= 1: # 13
        return 1 # 14
        print (f'==> {1}') # 6
        return 2 # 7
        print (f'==> {2}') # 6
        return 6 # 7
        print (f'==> {6}') # 6
        return result # 7
print(f"factorial(5) is : {6}") # 19
akbarza likes this post
Reply
#3
(Nov-09-2023, 01:13 PM)deanhystad Wrote:

thanks very much Smile Heart LOL
plz, replace factorial(5) with factorial(3). thanks again
buran write Nov-10-2023, 08:02 AM:
added spoiler tag, to hide the huge quoted text
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  problem in running a code akbarza 7 660 Feb-14-2024, 02:57 PM
Last Post: snippsat
  super() and order of running method in class inheritance akbarza 7 759 Feb-04-2024, 09:35 AM
Last Post: Gribouillis
  writing and running code in vscode without saving it akbarza 1 395 Jan-11-2024, 02:59 PM
Last Post: deanhystad
  Curious about decorator syntax rjdegraff42 14 2,132 May-03-2023, 01:21 PM
Last Post: rjdegraff42
  Code running many times nad not just one? korenron 4 1,376 Jul-24-2022, 08:12 AM
Last Post: korenron
  Error while running code on VSC maiya 4 3,776 Jul-01-2022, 02:51 PM
Last Post: maiya
  code running for more than an hour now, yet didn't get any result, what should I do? aiden 2 1,514 Apr-06-2022, 03:41 PM
Last Post: Gribouillis
  Why is this Python code running twice? mcva 5 5,296 Feb-02-2022, 10:21 AM
Last Post: mcva
  Python keeps running the old version of the code quest 2 3,789 Jan-20-2022, 07:34 AM
Last Post: ThiefOfTime
  My python code is running very slow on millions of records shantanu97 7 2,588 Dec-28-2021, 11:02 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020