{"id":1668,"date":"2024-03-16T17:26:44","date_gmt":"2024-03-16T11:56:44","guid":{"rendered":"https:\/\/geekpython.in\/?p=1668"},"modified":"2024-03-17T13:43:45","modified_gmt":"2024-03-17T08:13:45","slug":"decorators-in-python","status":"publish","type":"post","link":"https:\/\/geekpython.in\/decorators-in-python","title":{"rendered":"Decorators in Python: How They Work &#038; Creating Custom Decorators"},"content":{"rendered":"\n<p>You might have encountered functions or classes decorated with functions prefixed with <code>\"@\"<\/code>, for example, <code>@random<\/code>. These are known as decorators as they are placed above your class or function.<\/p>\n\n\n\n<p>In this tutorial, you will learn about:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Decorators in Python<\/li>\n\n\n\n<li>How to create a custom decorator<\/li>\n\n\n\n<li>The working of a decorator and how it modifies the original function<\/li>\n\n\n\n<li>How to create a custom decorator that accepts arguments and how it works<\/li>\n\n\n\n<li>Applying multiple decorators on top of a function and how they operate on the original function<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<p class=\"responsive-video-wrap clr\"><iframe loading=\"lazy\" title=\"What are Decorators in Python? 2MinutesPy\" width=\"1200\" height=\"675\" src=\"https:\/\/www.youtube.com\/embed\/tKCURAMFdd4?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen><\/iframe><\/p>\n<\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Decorator<\/h2>\n\n\n\n<p><strong>What is a decorator in Python?<\/strong> A decorator is an advanced function in Python that modifies the original function without changing its source code. It offers a way to add functionality to existing functions.<\/p>\n\n\n\n<p>If you want to create a class but don&#8217;t want to write the required magic methods (such as the <code>__init__<\/code> method) inside it, you can use the <a href=\"https:\/\/docs.python.org\/3\/library\/dataclasses.html\" target=\"_blank\" rel=\"noreferrer noopener\"><code>@dataclass<\/code><\/a> decorator on top of the class, and it will take care of the rest.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python mark:4 decode:true \"># @dataclass decorator example\nfrom dataclasses import dataclass\n\n@dataclass\nclass Pokemon:\n    name: str\n    high_power: int\n    combat_power: int\n\n    def double_hp(self):\n        return self.high_power * 2\n\nmonster = Pokemon(\"Charizard\", 200, 180)\nprint(monster.__dict__)\n\ncharizard_hp_doubled = monster.double_hp()\nprint(charizard_hp_doubled)<\/pre><\/div>\n\n\n\n<p>The <code>@dataclass<\/code> decorator adds the required magic method within the <code>Pokemon<\/code> class without changing the source code of the class.<\/p>\n\n\n\n<p>This class works just like any other normal class that contains the <code>__init__<\/code> method in Python, and you can access its attributes, and create methods.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tex decode:true \">{'name': 'Charizard', 'high_power': 200, 'combat_power': 180}\n400<\/pre><\/div>\n\n\n\n<p>By decorating <code>@dataclass<\/code> on top of the class eliminates the need to write the initializer method and other required methods within the class.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating a Custom Decorator<\/h2>\n\n\n\n<p>Although there are several pre-built decorator functions available, there is also a way to design a custom decorator function for a particular task.<\/p>\n\n\n\n<p>Consider the following simple decorator function that logs a message on the console whenever the original function is called.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \"># Decorator function\ndef log_message(func):\n    def wrapper():\n        print(f\"{func.__name__} function is called\")\n        func()\n    return wrapper<\/pre><\/div>\n\n\n\n<p>The <code>log_message()<\/code> function is a decorator function that accepts another function (<code>func<\/code>) as its argument. Inside <code>log_message()<\/code>, a <code>wrapper()<\/code> function is defined which prints a message and calls <code>func<\/code>.<\/p>\n\n\n\n<p>The <code>log_message()<\/code> returns the <code>wrapper<\/code>, effectively changing the behaviour of the original function (<code>func<\/code>).<\/p>\n\n\n\n<p>You can now create a normal function and decorate it with the <code>log_message()<\/code> decorator function.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python mark:4 decode:true \"># Decorator function\n...\n\n@log_message\ndef greet():\n    print(\"Welcome to GeekPython\")\n\ngreet()<\/pre><\/div>\n\n\n\n<p>Observe how the <code>greet()<\/code> function is decorated with the <code>log_message()<\/code> (<code>@log_message<\/code>) function. When decorating a function on top of another function, you have to stick to this convention.<\/p>\n\n\n\n<p>When you run this code, you&#8217;ll get the following result.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tex decode:true \">greet function is called\nWelcome to GeekPython<\/pre><\/div>\n\n\n\n<p>Notice that the <code>greet()<\/code> function prints a simple message but the <code>@log_message<\/code> decorator altered the behaviour of the <code>greet()<\/code> function by adding a message before calling the original function. This modification happens while preserving the signature of the original function (<code>greet()<\/code>).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Decorators Work?<\/h2>\n\n\n\n<p>Look at this part of the code from the above section where you used the <code>@log_message<\/code> to decorate the <code>greet()<\/code> function.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \">@log_message\ndef greet():\n    print(\"Welcome to GeekPython\")<\/pre><\/div>\n\n\n\n<p>The above code is equivalent to the following expression.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \">greeting = log_message(greet)<\/pre><\/div>\n\n\n\n<p>You will obtain the same outcome as before if you execute the code after making the following modifications.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python mark:11 decode:true \"># Decorator function\ndef log_message(func):\n    def wrapper():\n        print(f\"{func.__name__} function is called\")\n        func()\n    return wrapper\n\ndef greet():\n    print(\"Welcome to GeekPython\")\n\ngreeting = log_message(greet)\ngreeting()\n\n--------------------\ngreet function is called\nWelcome to GeekPython<\/pre><\/div>\n\n\n\n<p>The <code>greet()<\/code> function is passed to the <code>log_message()<\/code> function and stored inside the <code>greeting<\/code>. In the next line, the <code>greeting<\/code> is called just like any other function. What is happening and how does it work?<\/p>\n\n\n\n<p>After this line (<code>greeting = log_message(greet)<\/code>) is executed, the variable <code>greeting<\/code> points to the <code>wrapper()<\/code> returned by <code>log_message()<\/code>. If you print the variable <code>greeting<\/code>, you&#8217;ll get the reference of the <code>wrapper()<\/code> function.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \">greeting = log_message(greet)\nprint(greeting)\n\n--------------------\n&lt;function log_message.&lt;locals&gt;.wrapper at 0x0000024EF60C4C20&gt;<\/pre><\/div>\n\n\n\n<p>This <code>wrapper()<\/code> function prints a message and has a reference to the <code>greet()<\/code> function as <code>func<\/code> and it calls this function within its own body to maintain the original functionality while adding extra behaviour.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Defining Decorator Without Inner Function<\/h2>\n\n\n\n<p>One may wonder why the code in the <code>wrapper()<\/code> function cannot be inserted inside the scope of the <code>log_message()<\/code> function like in the following code.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \"># Decorator function\ndef log_message(func):\n    print(f\"{func.__name__} function is called\")\n    func()\n    return log_message\n\n@log_message\ndef greet():\n    print(\"Welcome to GeekPython\")\n\ngreet()<\/pre><\/div>\n\n\n\n<p>In the above code, the code inside the <code>wrapper()<\/code> function is now placed within the <code>log_message()<\/code> function&#8217;s scope. When you run the, you&#8217;ll see that the <code>greet()<\/code> function&#8217;s behaviour has changed but you get an error.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tex decode:true \">greet function is called\nWelcome to GeekPython\nTraceback (most recent call last):\n  ...\n    greet()\nTypeError: log_message() missing 1 required positional argument: 'func'<\/pre><\/div>\n\n\n\n<p>It says one argument is missing when you called the <code>greet()<\/code> function which means that the <code>greet()<\/code> function is now pointing to the <code>log_message()<\/code> function. But when you simply don&#8217;t call the <code>greet<\/code> function, it won&#8217;t throw any error.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \">...\n\n@log_message\ndef greet():\n    print(\"Welcome to GeekPython\")\n\ngreet\n\n--------------------\ngreet function is called\nWelcome to GeekPython<\/pre><\/div>\n\n\n\n<p>There is little flexibility and very little you can do with it, yet in certain instances it will work. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Handling Function Arguments Within Decorator<\/h2>\n\n\n\n<p><strong>What if you have a complex function that accepts arguments and processes them<\/strong>, then you can&#8217;t approach this problem in this way.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \"># Decorator function\ndef log_message(func):\n    print(f\"{func.__name__} function is called\")\n    func()\n    return log_message\n\n@log_message\ndef greet(user):\n    print(f\"Welcome to GeekPython: {user}\")\n\ngreet(\"Sachin\")<\/pre><\/div>\n\n\n\n<p>This code will result in an error as the <code>log_message()<\/code> function doesn&#8217;t have a nested inner function to handle the argument the <code>greet()<\/code> function accepts.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tex decode:true \">greet function is called\nTraceback (most recent call last):\n  ...\n    @log_message\n     ^^^^^^^^^^^\n  ...\n    func()\nTypeError: greet() missing 1 required positional argument: 'user'<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Defining Decorator With Inner Function to Handle Function Arguments<\/h3>\n\n\n\n<p>You can manage the arguments received by the <code>greet()<\/code> function by incorporating a nested function (<code>wrapper()<\/code>) within the <code>log_message()<\/code> decorator function, using <code>*args<\/code> and <code>**kwargs<\/code> as parameters.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python mark:3,5 decode:true \"># Decorator function\ndef log_message(func):\n    def wrapper(*args, **kwargs):\n        print(f\"{func.__name__} function is called\")\n        func(*args, **kwargs)\n    return wrapper\n\n@log_message\ndef greet(user):\n    print(f\"Welcome to GeekPython: {user}\")\n\ngreet(\"Sachin\")\n\n--------------------\ngreet function is called\nWelcome to GeekPython: Sachin<\/pre><\/div>\n\n\n\n<p>This time, the code printed the argument (<code>\"Sachin\"<\/code>) supplied to the <code>greet()<\/code> function when it was called, so you didn&#8217;t receive any errors.<\/p>\n\n\n\n<p>The <code>*args<\/code> and <code>**kwargs<\/code> passed to the <code>wrapper()<\/code> is used to pass on the arguments to <code>func<\/code> (a reference for the original function) that enables the decorator function to handle the arguments accepted by the original function.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Returning Values from Decorator<\/h3>\n\n\n\n<p>In the example above, using <code>greet(\"Sachin\")<\/code> resulted in the output. However, <strong>what if you wanted to return a value from the decorator?<\/strong><\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python mark:4,7 decode:true \">@log_message\ndef greet(user):\n    print(f\"Welcome to GeekPython: {user}\")\n    return f\"User: {user}\"\n\n# Trying to return a value\ngreeting = greet(\"Sachin\")\nprint(greeting)<\/pre><\/div>\n\n\n\n<p>Since your decorator <code>@log_message<\/code> doesn&#8217;t return a value directly, this code will return <code>None<\/code>.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tex decode:true \">greet function is called\nWelcome to GeekPython: Sachin\nNone<\/pre><\/div>\n\n\n\n<p>To handle this situation, you need to ensure that the <code>wrapper()<\/code> function returns the return value of the original function.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python mark:5 decode:true \"># Decorator function\ndef log_message(func):\n    def wrapper(*args, **kwargs):\n        print(f\"{func.__name__} function is called\")\n        return func(*args, **kwargs)\n    return wrapper<\/pre><\/div>\n\n\n\n<p>When you run the following code, you&#8217;ll get the value returned by the <code>greet()<\/code> function.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \"># Decorator function\ndef log_message(func):\n    def wrapper(*args, **kwargs):\n        print(f\"{func.__name__} function is called\")\n        return func(*args, **kwargs)\n    return wrapper\n\n@log_message\ndef greet(user):\n    print(f\"Welcome to GeekPython: {user}\")\n    return f\"User: {user}\"\n\ngreeting = greet(\"Sachin\")\nprint(greeting)\n\n--------------------\ngreet function is called\nWelcome to GeekPython: Sachin\nUser: Sachin<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Creating a Decorator that Accepts Argument<\/h2>\n\n\n\n<p>So far you&#8217;ve created simple decorators but decorators can also accept arguments. Consider the following decorator that accepts arguments.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \"># Decorator function to slice a string\ndef slice_string(start=0, end=0, step=None):\n    def slice_decorator(func):\n        def slice_wrapper(*args, **kwargs):\n            print(f\"Sliced from char {start} to char {end}.\")\n            if func(*args, **kwargs) == \"\":\n                print(\"Text is not long enough.\")\n            result = func(*args, **kwargs)\n            return result[start: end: step]\n\n        return slice_wrapper\n\n    return slice_decorator<\/pre><\/div>\n\n\n\n<p>In the above code, a decorator function <code>slice_string()<\/code> is defined. This (<code>slice_string()<\/code>) decorator function accepts three arguments: <code>start<\/code> (defaults to <code>0<\/code>), <code>end<\/code> (defaults to <code>0<\/code>), and <code>step<\/code> (defaults to <code>None<\/code>).<\/p>\n\n\n\n<p>Within this (<code>slice_string()<\/code>) function, the inner function, <code>slice_decorator()<\/code>, takes another function (<code>func<\/code>) as an argument and within the <code>slice_decorator()<\/code> function, a wrapper function (<code>slice_wrapper()<\/code>) is defined.<\/p>\n\n\n\n<p>The <code>slice_wrapper()<\/code> function takes any positional (<code>*args<\/code>) and keyword (<code>**kwargs<\/code>) arguments required to handle arguments if any accepted by the original function.<\/p>\n\n\n\n<p>The <code>slice_wrapper()<\/code> function prints a simple message, and in the next line, checks if the argument is an empty string, if it is then a message is printed otherwise, the result is sliced from the specified range.<\/p>\n\n\n\n<p>This <code>slice_wrapper()<\/code> function is returned by the <code>slice_decorator()<\/code> function and eventually, the <code>slice_decorator()<\/code> function is returned by the <code>slice_string()<\/code> function.<\/p>\n\n\n\n<p>Now you can create a function and decorate <code>@slice_string<\/code> on top of it.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python mark:4 decode:true \"># Decorator function to slice a string\n...\n\n@slice_string(2, 7)\ndef intro(text):\n    return text<\/pre><\/div>\n\n\n\n<p>The <code>intro()<\/code> function is defined that takes <code>text<\/code> as an argument and returns it. Two arguments (<code>2<\/code> and <code>7<\/code>) are passed to the <code>@slice_string<\/code> decorator, meaning the <code>text<\/code> will be sliced from the character at index 2 to index 7 (excluding the character at the 7th index).<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \"># Decorator function to slice a string\n...\n\nchars = intro(\"Welcome to GeekPython\")\nprint(chars)\n\n--------------------\nSliced from char 2 to char 7.\nlcome<\/pre><\/div>\n\n\n\n<p>Overall, a decorator function that accepts arguments typically involves the interaction of three functions: the outer function (the decorator itself) that accepts arguments, an inner function (the wrapper) that receives the original function, and a nested function (the innermost wrapper) that modifies the behaviour of the original function.<\/p>\n\n\n\n<p>Here is another example of a decorator that accepts an argument.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \">import time\n\ndef sleep_code(t):\n    def sleep_decorator(func):\n        def sleep_wrapper(*args, **kwargs):\n\n            # Calculate start time\n            start = time.perf_counter()\n            print(f\"Execution Delayed: {t} Seconds\")\n            # Sleep for t seconds\n            time.sleep(t)\n            # Calculate end time\n            end = time.perf_counter()\n            # Evaluate execution time\n            print(f\"Execution Took   : {round(end - start)} Seconds\")\n\n            return func(*args, **kwargs)\n        return sleep_wrapper\n    return sleep_decorator\n\n@sleep_code(5)\ndef slow_down(x, y):\n    return x**y\n\nobj = slow_down(2, 3)\nprint(obj)<\/pre><\/div>\n\n\n\n<p>The <code>@sleep_code<\/code> decorator takes an argument <code>t<\/code> representing time in seconds. It modifies the behaviour of the original function (<code>slow_down()<\/code>) by delaying its execution using <code>time.sleep(t)<\/code> within the innermost function (<code>sleep_wrapper()<\/code>). Additionally, before returning the result, it prints the execution time taken by the code, which is measured using <code>time.perf_counter()<\/code>.<\/p>\n\n\n\n<p>When you run the code, you&#8217;ll get the following result.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tex decode:true \">Execution Delayed: 5 Seconds\nExecution Took   : 5 Seconds\n8<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Stacking Multiple Decorators on Top of a Function<\/h2>\n\n\n\n<p>So far you might have a pretty good idea about decorators and in this section, you&#8217;ll see that multiple decorator functions can be stacked on top of another function. Here&#8217;s a simple example.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python mark:16-17 decode:true \"># First decorator function\ndef decorator__1(func):\n    def wrapper_d1(*args, **kwargs):\n        print(f\"Called decorator 1\")\n        return func(*args, **kwargs)\n    return wrapper_d1\n\n# Second decorator function\ndef decorator_2(func):\n    def wrapper_d2(*args, **kwargs):\n        print(f\"Called decorator 2\")\n        return func(*args, **kwargs)\n    return wrapper_d2\n\n# Decorated with multiple decorators\n@decorator_1\n@decorator_2\ndef log_message():\n    return \"Message logged\"\n\nmessage = log_message()\nprint(message)<\/pre><\/div>\n\n\n\n<p>Both <code>decorator_1()<\/code> and <code>decorator_2()<\/code> have the same boilerplate and log a simple message.<\/p>\n\n\n\n<p>The <code>log_message()<\/code> is decorated with both (<code>@decorator_1<\/code> and <code>@decorator_2<\/code>) decorators with the <code>@decorator_1<\/code> being on the topmost level followed by the <code>@decorator_2<\/code>.<\/p>\n\n\n\n<p>When you run this code, you&#8217;ll get the following result.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tex decode:true \">Called decorator 1\nCalled decorator 2\nMessage logged<\/pre><\/div>\n\n\n\n<p>You can see that messages logged by the decorators are in the exact order as they are stacked on top of the <code>log_message()<\/code> function.<\/p>\n\n\n\n<p>If you reverse the order of these decorators, the messages will be logged in the same order as well.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python mark:2-3 decode:true \"># Reversed the order of the decorators\n@decorator_2\n@decorator_1\ndef log_message():\n    return \"Message logged\"\n\nmessage = log_message()\nprint(message)\n\n--------------------\nCalled decorator 2\nCalled decorator 1\nMessage logged<\/pre><\/div>\n\n\n\n<p>The code is equivalent to passing <code>log_message()<\/code> through <code>decorator_1()<\/code> first, and then passing the result (<code>decorator_1(log_message)<\/code>) through <code>decorator_2()<\/code>.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \">message = decorator_2(decorator_1(log_message)<\/pre><\/div>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Note: When you are stacking multiple decorators on top of the function, their order matters.<\/strong><\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Practical Example<\/h3>\n\n\n\n<p>Here&#8217;s an example that shows when decorating a function with multiple decorators, they need to be in order.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \">@slice_string(2, 7)\n@sleep_code(2)\ndef intro(text):\n    return text\n\nchars = intro(\"Welcome to GeekPython\")\nprint(chars)<\/pre><\/div>\n\n\n\n<p>When you run this code, the execution will delayed for 4 seconds because the <code>sleep_code()<\/code> will be invoked twice.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tex decode:true \">Sliced from char 2 to char 7.\nExecution Delayed: 2 Seconds\nExecution Took   : 2 Seconds\nExecution Delayed: 2 Seconds\nExecution Took   : 2 Seconds\nlcome<\/pre><\/div>\n\n\n\n<p>If you just reverse the order of the decorators in the above code, that would just work fine.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python mark:1-2 decode:true \">@sleep_code(2)\n@slice_string(2, 7)\ndef intro(text):\n    return text\n\nchars = intro(\"Welcome to GeekPython\")\nprint(chars)<\/pre><\/div>\n\n\n\n<p><strong>Output<\/strong><\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tex decode:true \">Execution Delayed: 2 Seconds\nExecution Took   : 2 Seconds\nSliced from char 2 to char 7.\nlcome<\/pre><\/div>\n\n\n\n<p>You can observe the difference in the output in which the execution of the code took only 2 seconds. That&#8217;s why you need to ensure that the decorators are in the correct order above the function.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p><strong>Decorators<\/strong> modify the behaviour of the original function without changing the source code of the original function. They are advanced functions that do modification while preserving the original function&#8217;s signature.<\/p>\n\n\n\n<p>Python has several built-in decorator functions, and you can also create the custom decorator your program may need.<\/p>\n\n\n\n<p>You saw when you define a custom decorator, you create a function returning a wrapper function. This wrapper function handles the modification and if your decorated function accepts arguments then it uses <code>*args<\/code> and <code>**kwargs<\/code> to pass on arguments. If the decorator function accepts arguments then you end up nesting the wrapper function into another function.<\/p>\n\n\n\n<p>You also observed that in order to get the appropriate outcome, decorators must be stacked correctly on top of any function.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\ud83c\udfc6<strong>Other articles you might be interested in if you liked this one<\/strong><\/p>\n\n\n\n<p>\u2705<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"https:\/\/geekpython.in\/understanding-if-__name__-__main__-in-python-programs\">Why if __name__ == &#8220;__main__&#8221; is used in Python programs<\/a>?<\/p>\n\n\n\n<p>\u2705<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"https:\/\/geekpython.in\/pickle-module-in-python\">Serialize and deserialize Python objects using the pickle module<\/a>.<\/p>\n\n\n\n<p>\u2705<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"https:\/\/geekpython.in\/build-websocket-server-and-client-using-python\">Create a WebSocket server and client in Python<\/a>.<\/p>\n\n\n\n<p>\u2705<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"https:\/\/geekpython.in\/create-and-integrate-mysql-database-with-flask-app\">Create and integrate MySQL database with Flask app using Python<\/a>.<\/p>\n\n\n\n<p>\u2705<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"https:\/\/geekpython.in\/python-getitem-method\">What is __getitem__ method in Python class<\/a>?<\/p>\n\n\n\n<p>\u2705<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"https:\/\/geekpython.in\/yield-keyword-in-python\">What is the yield keyword in Python and how it is different from the return keyword<\/a>?<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>That&#8217;s all for now<\/strong><\/p>\n\n\n\n<p><strong>Keep Coding\u270c\u270c<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>You might have encountered functions or classes decorated with functions prefixed with &#8220;@&#8221;, for example, @random. These are known as decorators as they are placed above your class or function. In this tutorial, you will learn about: Decorator What is a decorator in Python? A decorator is an advanced function in Python that modifies the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1672,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ocean_post_layout":"","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"","ocean_second_sidebar":"","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"","ocean_custom_header_template":"","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"","ocean_menu_typo_font_family":"","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"","ocean_post_oembed":"","ocean_post_self_hosted_media":"","ocean_post_video_embed":"","ocean_link_format":"","ocean_link_format_target":"self","ocean_quote_format":"","ocean_quote_format_link":"post","ocean_gallery_link_images":"on","ocean_gallery_id":[],"footnotes":""},"categories":[2,71],"tags":[31],"class_list":["post-1668","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python","category-misc","tag-python3","entry","has-media"],"_links":{"self":[{"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/posts\/1668","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/comments?post=1668"}],"version-history":[{"count":9,"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/posts\/1668\/revisions"}],"predecessor-version":[{"id":1684,"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/posts\/1668\/revisions\/1684"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/media\/1672"}],"wp:attachment":[{"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/media?parent=1668"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/categories?post=1668"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/geekpython.in\/wp-json\/wp\/v2\/tags?post=1668"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}