<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ decorator - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ decorator - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 06 Jun 2026 11:17:48 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/decorator/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ What are Decorators in Python? Explained with Code Examples ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you will learn about Python decorators: what they are, how they work, and when to use them. Table of Contents Foundation for Decorators [Introduction to Python Decorators](#Introduction to Python Decorators) Creating Simple Decorat... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/decorators-in-python-tutorial/</link>
                <guid isPermaLink="false">66c7217e87ceefbdaf9b9217</guid>
                
                    <category>
                        <![CDATA[ decorator ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Samyak Jain ]]>
                </dc:creator>
                <pubDate>Tue, 18 Jun 2024 18:53:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/decorators-in-python.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you will learn about Python decorators: what they are, how they work, and when to use them.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ol>
<li><a class="post-section-overview" href="#heading-foundation-for-decorators">Foundation for Decorators</a></li>
<li>[Introduction to Python Decorators](#Introduction to Python Decorators)</li>
<li><a class="post-section-overview" href="#heading-now-lets-look-at-a-decorator-example">Creating Simple Decorators</a><br>– <a class="post-section-overview" href="#heading-applying-decorators-to-functions">Applying Decorators to Functions</a><br>– <a class="post-section-overview" href="#heading-using-the-syntax-for-decorators">Using the @ Syntax for Decorators</a></li>
<li><a class="post-section-overview" href="#heading-how-to-handle-functions-with-arguments">How to Handle Functions with Arguments</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-classes-as-decorators">Using Classes as Decorators</a></li>
<li><a class="post-section-overview" href="#heading-best-practices-for-using-decorators">Best Practices for Using Decorators</a></li>
<li><a class="post-section-overview" href="#heading-practical-applications-of-decorators">Real-World Applications of Decorators</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<p>Decorators are a powerful and elegant way to extend the behavior of functions or methods without modifying their actual code. But before diving into decorators, it's helpful to understand two foundational concepts in Python: first-class functions and closures.</p>
<h2 id="heading-foundation-for-decorators">Foundation for Decorators</h2>
<h3 id="heading-first-class-functions-in-python">First-Class Functions in Python</h3>
<p>First-class functions mean that functions in Python are treated like any other object. This implies that functions can be:</p>
<ul>
<li>Passed as arguments to other functions.</li>
<li>Returned from other functions.</li>
<li>Assigned to variables.</li>
</ul>
<h3 id="heading-understanding-closures">Understanding Closures</h3>
<p>Closures in Python allow a function to remember the environment in which it was created. This means the inner function has access to the variables in the local scope of the outer function even after the outer function has finished executing.</p>
<p>Let’s look at an example to understand closures:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">outer_func</span>():</span>
    greet = <span class="hljs-string">"Hello!"</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inner_func</span>():</span>
        print(greet)

    <span class="hljs-keyword">return</span> inner_func

new_function = outer_func()
new_function()  <span class="hljs-comment"># Outputs: Hello!</span>
new_function()  <span class="hljs-comment"># Outputs: Hello!</span>
</code></pre>
<p>In this example:</p>
<ul>
<li>We have <code>outer_func</code> that doesn't take any parameters but has a local variable <code>greet</code>.</li>
<li>An <code>inner_func</code> is defined within <code>outer_func</code> that prints <code>greet</code>.</li>
<li>When we call <code>outer_func</code>, it returns <code>inner_func</code> but does not execute it immediately. We assign the returned function to <code>new_function</code>. Now, <code>new_function</code> can be called later, and it will remember the <code>greet</code> variable from <code>outer_func</code>’s scope, printing "Hello!" each time it’s called.</li>
</ul>
<p>This is what a closure is—it remembers our <code>greet</code> variable even after the outer function has finished executing.</p>
<h4 id="heading-modifying-closures-with-parameters">Modifying Closures with Parameters</h4>
<p>Let's enhance our closure by passing a parameter to the <code>outer_func</code> instead of using a local variable:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">outer_func</span>(<span class="hljs-params">greet</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inner_func</span>():</span>
        print(greet)
    <span class="hljs-keyword">return</span> inner_func

namaste_func = outer_func(<span class="hljs-string">"Namaste!"</span>)
howdy_func = outer_func(<span class="hljs-string">"Howdy!"</span>)

namaste_func()  <span class="hljs-comment"># Outputs: Namaste!</span>
howdy_func()    <span class="hljs-comment"># Outputs: Howdy!</span>
</code></pre>
<p>Here:</p>
<ul>
<li><code>outer_func</code> now takes a parameter <code>greet</code>.</li>
<li>The <code>inner_func</code> prints this <code>greet</code>.</li>
<li>When we call <code>outer_func</code> with "Namaste!" and "Howdy!", it returns functions that remember these specific messages.</li>
</ul>
<p>So, this was a quick brief about first-class functions and closures. If you want to learn more about them you can read this comprehensive blog <a target="_blank" href="https://www.freecodecamp.org/news/first-class-functions-and-closures-in-python/">here</a>.</p>
<h2 id="heading-introduction-to-python-decorators"><strong>Introduction to Python Decorators</strong></h2>
<p>A decorator is a function that takes another function as an argument, adds some functionality, and returns a new function. This allows you to "wrap" another function to extend its behavior (adding some functionality before or after) without modifying the original function's source code.</p>
<p>So, this is the closure example that we used above:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">outer_func</span>(<span class="hljs-params">greet</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inner_func</span>():</span>
        print(greet)
    <span class="hljs-keyword">return</span> inner_func
</code></pre>
<h3 id="heading-now-lets-look-at-a-decorator-example">Now, let's look at a Decorator Example:</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorator_function</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper_function</span>():</span>
        <span class="hljs-keyword">return</span> func()
    <span class="hljs-keyword">return</span> wrapper_function
</code></pre>
<p>Here, instead of a value (like <code>greet</code>), we're accepting a function (<code>func</code>) as an argument. Within our <code>wrapper_function</code>, instead of just printing out a message, we're going to execute this <code>func</code> and then return that.</p>
<h3 id="heading-applying-decorators-to-functions">Applying Decorators to Functions</h3>
<p>Here's how we can apply our decorator to a simple function:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorator_function</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper_function</span>():</span>
        <span class="hljs-keyword">return</span> func()
    <span class="hljs-keyword">return</span> wrapper_function

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display</span>():</span>
    print(<span class="hljs-string">'The display function was called'</span>)

decorated_display = decorator_function(display)
decorated_display()  <span class="hljs-comment"># Outputs: The display function was called</span>
</code></pre>
<p>In this example:</p>
<ul>
<li>We define a simple function <code>display</code> that prints a message.</li>
<li>We apply the <code>decorator_function</code> to <code>display</code>, creating a new variable<code>decorated_display</code>.</li>
<li>When we call <code>decorated_display()</code>, it runs the <code>wrapper_function</code> inside our decorator, which in turn calls and returns the <code>display</code> function.</li>
</ul>
<h3 id="heading-using-the-syntax-for-decorators">Using the @ Syntax for Decorators</h3>
<p>Python provides a more readable way to apply decorators using the <code>@</code> symbol. This syntax is easier to understand and is commonly used in Python code:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorator_function</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper_function</span>():</span>
        print(<span class="hljs-string">f'Wrapper executed before <span class="hljs-subst">{func.__name__}</span>'</span>)
        <span class="hljs-keyword">return</span> func()
    <span class="hljs-keyword">return</span> wrapper_function

<span class="hljs-meta">@decorator_function</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display</span>():</span>
    print(<span class="hljs-string">'The display function was called'</span>)

display()  <span class="hljs-comment"># Outputs: Wrapper executed before display</span>
           <span class="hljs-comment">#          The display function was called</span>
</code></pre>
<p>Here:</p>
<ul>
<li>We use <code>@decorator_function</code> decorator above the <code>display</code> function definition which is equivalent to <code>display = decoratorFunction(display)</code>.</li>
<li>Now, when we call <code>display()</code>, it automatically goes through the decorator, printing the additional message first.</li>
</ul>
<h2 id="heading-how-to-handle-functions-with-arguments">How to Handle Functions with Arguments</h2>
<p>The decorator we've written so far won't work if our original function takes arguments. For example, consider the following function:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display_info</span>(<span class="hljs-params">name, age</span>):</span>
    print(<span class="hljs-string">'display_info was called with ({}, {})'</span>.format(name, age))

display_info(<span class="hljs-string">'Kalam'</span>, <span class="hljs-number">83</span>)  <span class="hljs-comment"># Outputs: display_info was called with (Kalam, 83)</span>
</code></pre>
<p>If we try to apply our current decorator to <code>display_info</code>, it will raise an error because the <code>wrapperFunction</code> takes no arguments but the original function expects two.</p>
<h3 id="heading-modifying-the-decorator-to-handle-arguments">Modifying the Decorator to Handle Arguments</h3>
<p>We can modify our decorator to accept any number of positional and keyword arguments by using <code>*args</code> and <code>**kwargs</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> functools

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decoratorFunction</span>(<span class="hljs-params">func</span>):</span>
<span class="hljs-meta">    @functools.wraps(func)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapperFunction</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        print(<span class="hljs-string">'Wrapper executed before {}'</span>.format(func.__name__))
        <span class="hljs-keyword">return</span> func(*args, **kwargs)
    <span class="hljs-keyword">return</span> wrapperFunction

<span class="hljs-meta">@decoratorFunction</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display</span>():</span>
    print(<span class="hljs-string">'The display function was called'</span>)

<span class="hljs-meta">@decoratorFunction</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display_info</span>(<span class="hljs-params">name, age</span>):</span>
    print(<span class="hljs-string">'display_info was called with ({}, {})'</span>.format(name, age))

display_info(<span class="hljs-string">'Kalam'</span>, <span class="hljs-number">83</span>)  
display()
</code></pre>
<p>In this updated decorator:</p>
<ul>
<li><code>wrapperFunction</code> now accepts any number of positional (<code>*args</code>) and keyword arguments (<code>**kwargs</code>).</li>
<li>These arguments are passed to <code>func</code> when it is called inside <code>wrapperFunction</code>.</li>
</ul>
<p>The output of this will be:</p>
<pre><code>Wrapper executed before display_info
display_info was called <span class="hljs-keyword">with</span> (Kalam, <span class="hljs-number">83</span>)
Wrapper executed before display
The display <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">was</span> <span class="hljs-title">called</span></span>
</code></pre><p>This setup makes our decorator flexible enough to handle any function, regardless of its parameters.</p>
<p>BTW, Notice how we added new functionality to two different functions (<code>display()</code> and <code>display_info()</code>) without altering them? This is one of the main benefits of decorators: they allow us to extend the behavior of several functions in a DRY (Don't Repeat Yourself) way, as demonstrated in this example.</p>
<h2 id="heading-how-to-use-classes-as-decorators">How to Use Classes as Decorators</h2>
<p>While function-based decorators are common, you can also use classes to create decorators. Using classes as decorators can offer more flexibility and readability, especially for complex decorators.</p>
<p>To help you understand them better, We'll turn a function-based decorator into a class-based decorator:</p>
<h3 id="heading-original-function-based-decorator">Original Function-Based Decorator</h3>
<p>Let's start with a simple function-based decorator:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decoratorFunction</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapperFunction</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        print(<span class="hljs-string">'Wrapper executed before calling {}'</span>.format(func.__name__))
        <span class="hljs-keyword">return</span> func(*args, **kwargs)
    <span class="hljs-keyword">return</span> wrapperFunction
</code></pre>
<h3 id="heading-creating-a-class-based-decorator">Creating a Class-Based Decorator</h3>
<p>To turn this function-based decorator into a class-based decorator, follow these steps:</p>
<p><strong>Step 1: Define the Class</strong><br>First, we define a new class called <code>DecoratorClass</code>. This class will handle the decoration process.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DecoratorClass</span>:</span>
    <span class="hljs-keyword">pass</span>
</code></pre>
<p><strong>Step 2: Implement the</strong> <strong><code>__init__</code> Method</strong><br>The <code>__init__</code> is a special method that initializes the object when an instance of the class is created.<br>Next, we pass the function to be decorated (<code>func</code>) as an argument to the <code>__init__</code> method and store it in an instance variable <code>self.func</code>.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DecoratorClass</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, func</span>):</span>
        self.func = func
</code></pre>
<p><strong>Step 3: Implement the <code>__call__</code> Method</strong><br>The <code>__call__</code> method is a special method that allows an instance of the class to be called as a function. This method is essential because it handles the actual decoration logic. In this case:</p>
<ul>
<li>The <code>__call__</code> method takes <code>*args</code> and <code>**kwargs</code> to handle any number of positional and keyword arguments.</li>
<li>Inside <code>__call__</code>, we print a message and then call the original function with its arguments.</li>
</ul>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DecoratorClass</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, func</span>):</span>
        self.func = func

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__call__</span>(<span class="hljs-params">self, *args, **kwargs</span>):</span>
        print(<span class="hljs-string">'Executing wrapper before {}'</span>.format(self.func.__name__))
        <span class="hljs-keyword">return</span> self.func(*args, **kwargs)
</code></pre>
<h3 id="heading-using-the-class-based-decorator">Using the Class-Based Decorator</h3>
<p>We can now use the <code>@</code> syntax to apply the class-based decorator to functions, just as we did with the function-based decorator.</p>
<pre><code class="lang-python"><span class="hljs-meta">@DecoratorClass</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display</span>():</span>
    print(<span class="hljs-string">'display function executed'</span>)

<span class="hljs-meta">@DecoratorClass</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display_info</span>(<span class="hljs-params">name, age</span>):</span>
    print(<span class="hljs-string">'display_info function executed with arguments ({}, {})'</span>.format(name, age))
</code></pre>
<h3 id="heading-running-the-decorated-functions">Running the Decorated Functions</h3>
<p>When we call the decorated functions, the <code>__call__</code> method of <code>DecoratorClass</code> is executed:</p>
<pre><code class="lang-python">display_info(<span class="hljs-string">'Kalam'</span>, <span class="hljs-number">83</span>)
display()
</code></pre>
<h3 id="heading-complete-example">Complete Example</h3>
<p>Here is the complete example with the class-based decorators:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DecoratorClass</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, func</span>):</span>
        self.func = func

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__call__</span>(<span class="hljs-params">self, *args, **kwargs</span>):</span>
        print(<span class="hljs-string">'Executing wrapper before {}'</span>.format(self.func.__name__))
        <span class="hljs-keyword">return</span> self.func(*args, **kwargs)

<span class="hljs-meta">@DecoratorClass</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display</span>():</span>
    print(<span class="hljs-string">'display function executed'</span>)

<span class="hljs-meta">@DecoratorClass</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display_info</span>(<span class="hljs-params">name, age</span>):</span>
    print(<span class="hljs-string">'display_info function executed with arguments ({}, {})'</span>.format(name, age))

display_info(<span class="hljs-string">'Kalam'</span>, <span class="hljs-number">83</span>)
display()
</code></pre>
<p>In this class-based decorator:</p>
<ul>
<li><strong><code>__init__</code> Method:</strong> This method binds the original function to an instance of the class.</li>
<li><strong><code>__call__</code> Method:</strong> This method allows an instance of <code>DecoratorClass</code> to be called as a function. It prints a message and then calls the original function with any provided arguments.</li>
<li><strong>Decorating Functions:</strong> We use the <code>@DecoratorClass</code> syntax to decorate the <code>display</code> and <code>display_info</code> functions.</li>
<li><strong>Execution:</strong> When <code>display_info('Kalam', 83)</code> is called, the <code>__call__</code> method of <code>DecoratorClass</code> is executed, printing the message and then executing <code>display_info</code>. Similarly, when <code>display()</code> is called, it executes the <code>__call__</code> method, prints the message, and then executes <code>display</code>.</li>
</ul>
<p>Both function-based and class-based decorators provide the same functionality. The choice between them depends on personal preference and the complexity of the decorator logic.</p>
<h2 id="heading-best-practices-for-using-decorators">Best Practices for Using Decorators</h2>
<p>When using decorators in Python, it's essential to follow best practices to maintain clean, maintainable code that aligns with Pythonic conventions.</p>
<h4 id="heading-1-preserve-function-metadata-with-functoolswraps">1. Preserve Function Metadata with <code>functools.wraps</code></h4>
<p>When you create a decorator, the original function's metadata (such as its name, docstring, and module) is often lost. This can lead to confusion and issues with introspection, documentation, and debugging. To preserve this metadata, use the <code>functools.wraps</code> decorator within your wrapper function.</p>
<p><code>functools.wraps</code> was introduced in Python 2.5 as part of the <code>functools</code> module, which provides higher-order functions and operations on callable objects. The <code>wraps</code> decorator is specifically designed to update the wrapper function to look more like the wrapped function by copying attributes such as the function name, module, and docstring (yes, you guessed it right - <code>functools.wraps()</code> itself is a decorator). </p>
<p>Let's see an Example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> functools

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decoratorFunction</span>(<span class="hljs-params">func</span>):</span>
<span class="hljs-meta">    @functools.wraps(func)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapperFunction</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        print(<span class="hljs-string">f'Wrapper executed before <span class="hljs-subst">{func.__name__}</span>'</span>)
        <span class="hljs-keyword">return</span> func(*args, **kwargs)
    <span class="hljs-keyword">return</span> wrapperFunction

<span class="hljs-meta">@decoratorFunction</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display</span>():</span>
    <span class="hljs-string">"""Display function docstring"""</span>
    print(<span class="hljs-string">'The display function was called'</span>)

print(display.__name__)   <span class="hljs-comment"># Outputs: display</span>
print(display.__doc__)    <span class="hljs-comment"># Outputs: Display function docstring</span>
</code></pre>
<p>In this example, <code>@functools.wraps(func)</code> is used to ensure that the <code>wrapperFunction</code> retains the original <code>func</code>'s metadata.</p>
<h4 id="heading-2-keep-decorators-simple-and-focused">2. Keep Decorators Simple and Focused</h4>
<p>A decorator should have a single responsibility and should not try to do too many things. If a decorator becomes complex, consider breaking it down into multiple, simpler decorators that can be composed together. Example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> functools

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">log_function_call</span>(<span class="hljs-params">func</span>):</span>
<span class="hljs-meta">    @functools.wraps(func)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        print(<span class="hljs-string">f'Calling <span class="hljs-subst">{func.__name__}</span>'</span>)
        <span class="hljs-keyword">return</span> func(*args, **kwargs)
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">measure_time</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-keyword">import</span> time
<span class="hljs-meta">    @functools.wraps(func)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(<span class="hljs-string">f'<span class="hljs-subst">{func.__name__}</span> took <span class="hljs-subst">{end - start}</span> seconds'</span>)
        <span class="hljs-keyword">return</span> result
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@log_function_call</span>
<span class="hljs-meta">@measure_time</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">compute_square</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-keyword">return</span> n * n

print(compute_square(<span class="hljs-number">5</span>))
</code></pre>
<p>In this example, <code>log_function_call</code> and <code>measure_time</code> are simple, single-responsibility decorators that can be composed to add both logging and timing functionality to <code>compute_square</code>. This is what Decorators do - providing a clean and readable way to implement common patterns like logging and timing.</p>
<h4 id="heading-3-use-descriptive-names-for-decorators-and-wrapped-functions">3. Use Descriptive Names for Decorators and Wrapped Functions</h4>
<p>Choose clear and descriptive names for your decorators and the functions they wrap so they clearly indicates their functionality. This makes the purpose and behavior of the code more apparent. </p>
<h4 id="heading-4-document-your-decorators">4. Document Your Decorators</h4>
<p>Always document your decorators, explaining their purpose and how they should be used. This is especially important if others will use your decorators or if you are working in a team.</p>
<h2 id="heading-practical-applications-of-decorators">Practical Applications of Decorators</h2>
<p>Now you might be wondering, "Okay, decorators are fancy and all, but how and where do we actually use them?" Well, here are some practical applications:</p>
<ul>
<li><strong>Logging Function Calls</strong>:<br>Logging is a common requirement for tracking the usage of functions and methods, especially in debugging and monitoring applications.</li>
<li><strong>Timing Functions</strong>:<br>Decorators can measure the time it takes for a function to execute, which is useful for performance analysis.</li>
</ul>
<p>We have seen both the examples above in the <a class="post-section-overview" href="#heading-2-keep-decorators-simple-and-focused">best practices section.</a></p>
<p>Beyond these common uses, there are other usecases such as:</p>
<ul>
<li><strong>Input Validation:</strong><br>Decorators can be used to validate inputs to functions, ensuring that they meet certain criteria before the function proceeds.</li>
<li><strong>Memoization</strong>:<br>The <code>memoize</code> function is a decorator that helps to cache (store) the results of expensive function calls and reuse the cached result when the same inputs occur again. This technique is called Memoization and it is useful to optimize the performance, especially for recursive functions like calculating Fibonacci numbers.</li>
</ul>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">validate_non_negative</span>(<span class="hljs-params">func</span>):</span>
<span class="hljs-meta">    @wraps(func)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        <span class="hljs-keyword">if</span> any(arg &lt; <span class="hljs-number">0</span> <span class="hljs-keyword">for</span> arg <span class="hljs-keyword">in</span> args):
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Arguments must be non-negative"</span>)
        <span class="hljs-keyword">return</span> func(*args, **kwargs)
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@validate_non_negative</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">square_root</span>(<span class="hljs-params">x</span>):</span>
    <span class="hljs-keyword">return</span> x ** <span class="hljs-number">0.5</span>

print(square_root(<span class="hljs-number">4</span>))
</code></pre>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> functools

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">memoize</span>(<span class="hljs-params">func</span>):</span>
    cache = {}
<span class="hljs-meta">    @functools.wraps(func)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args</span>):</span>
        <span class="hljs-keyword">if</span> args <span class="hljs-keyword">in</span> cache:
            <span class="hljs-keyword">return</span> cache[args]
        result = func(*args)
        cache[args] = result
        <span class="hljs-keyword">return</span> result
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@memoize</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fibonacci</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-keyword">if</span> n <span class="hljs-keyword">in</span> {<span class="hljs-number">0</span>, <span class="hljs-number">1</span>}:
        <span class="hljs-keyword">return</span> n
    <span class="hljs-keyword">return</span> fibonacci(n - <span class="hljs-number">1</span>) + fibonacci(n - <span class="hljs-number">2</span>)

fibonacci(<span class="hljs-number">10</span>)
</code></pre>
<p>Run <a target="_blank" href="https://gist.github.com/theSamyak/09a54ed5a6cc0380ee34a1a527f2c9e8">this function</a> to see the time difference when running Fibonacci function with or without memoization.</p>
<ul>
<li><strong>Access Control and Authentication</strong>:<br>In web applications, access control and authentication are crucial for security. Decorators can be used to enforce user permissions, ensuring that only authorized users can access certain functions or endpoints.</li>
</ul>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">requires_login</span>(<span class="hljs-params">func</span>):</span>
<span class="hljs-meta">    @wraps(func)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user_is_logged_in():
            <span class="hljs-keyword">raise</span> Exception(<span class="hljs-string">"User not logged in"</span>)
        <span class="hljs-keyword">return</span> func(*args, **kwargs)
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@requires_login</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">view_dashboard</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Dashboard content"</span>

<span class="hljs-comment"># user_is_logged_in is a placeholder for the actual authentication check function.</span>
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Decorators in Python provide a clean and powerful way to extend the behavior of functions. By understanding first-class functions and closures, you can grasp how decorators work under the hood.</p>
<p>Whether you're using function-based or class-based decorators, you can enhance your functions without altering their original code, keeping your codebase clean and maintainable.</p>
<ul>
<li>Decorators are powerful for extending the functionality of functions.</li>
<li>They can be implemented using functions or classes.</li>
<li>The <code>@decorator</code> syntax is a cleaner and more readable way to apply decorators.</li>
<li>They help keep your code DRY (Don't Repeat Yourself) by abstracting common functionality.</li>
</ul>
<p><strong>Thank you for reading!</strong> If you have any comments, criticism, or questions, feel free to tweet or reach out to me at @<a target="_blank" href="https://x.com/OGsamyak">OGsamyak</a>. Your feedback helps me improve!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Python Decorator Handbook ]]>
                </title>
                <description>
                    <![CDATA[ Python decorators provide an easy yet powerful syntax for modifying and extending the behavior of functions in your code. A decorator is essentially a function that takes another function, augments its functionality, and returns a new function – with... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-python-decorator-handbook/</link>
                <guid isPermaLink="false">66d45d9f052ad259f07e4a69</guid>
                
                    <category>
                        <![CDATA[ decorator ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python 3 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Atharva Shah ]]>
                </dc:creator>
                <pubDate>Fri, 26 Jan 2024 17:17:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/The-Python-Decorator-Handbook-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Python decorators provide an easy yet powerful syntax for modifying and extending the behavior of functions in your code.</p>
<p>A decorator is essentially a function that takes another function, augments its functionality, and returns a new function – without permanently modifying the original function itself.</p>
<p>This tutorial will walk you through 11 handy decorators to help add functionality like timing execution, caching, rate limiting, debugging and more. Whether you want to profile performance, improve efficiency, validate data, or manage errors, these decorators have got you covered!</p>
<p>The examples here focus on the common usage patterns and utilities of decorators that can come in handy in your day-to-day programming and save you a lot of effort. Understanding the flexibility of decorators will help you write clean, resilient, and optimized application code.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<p>Here are the decorators covered in this tutorial:</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-log-arguments-and-return-value-of-a-function">Log Arguments and Return Value of a Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-get-the-execution-time-of-a-function">Get the Execution Time of a Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-convert-function-return-value-to-a-specified-data-type">Convert Function Return Value to a Specified Data Type</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-cache-function-results">Cache Function Results</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-validate-function-arguments-based-on-condition">Validate Function Arguments Based on Condition</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-retry-a-function-multiple-times-on-failure">Retry a Function Multiple Times on Failure</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-enforce-rate-limits-on-a-function">Enforce Rate Limits on a Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-handle-exceptions-and-provide-default-response">Handle Exceptions and Provide Default Response</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-enforce-type-checking-on-function-arguments">Enforce Type Checking on Function Arguments</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-measure-memory-usage-of-a-function">Measure Memory Usage of a Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-cache-function-results-with-expiration-time">Cache Function Results with Expiration Time</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<p>But first, a little introduction.</p>
<h2 id="heading-how-python-decorators-work">How Python Decorators Work</h2>
<p>Before diving in, let's understand some key benefits of decorators in Python:</p>
<ul>
<li><p><strong>Enhancing functions without invasive changes:</strong> Decorators augment functions transparently without altering the original code, keeping the core logic clean and maintainable.</p>
</li>
<li><p><strong>Reusing functionality across places:</strong> Common capabilities like logging, caching, and rate limiting can be built once in decorators and applied wherever needed.</p>
</li>
<li><p><strong>Readable and declarative syntax:</strong> The <code>@decorator</code> syntax simply conveys functionality enhancement at the definition site.</p>
</li>
<li><p><strong>Modularity and separation of concerns:</strong> Decorators promote loose coupling between functional logic and secondary capabilities like performance, security, logging etc.</p>
</li>
</ul>
<p>The takeaway is that decorators unlock simple yet flexible ways of transparently enhancing Python functions for improved code organization, efficiency, and reuse without introducing complexity or redundancy.</p>
<p>Here is a basic example of decorator syntax in Python with annotations:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Decorator function</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_decorator</span>(<span class="hljs-params">func</span>):</span>

<span class="hljs-comment"># Wrapper function</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>():</span>
        print(<span class="hljs-string">"Before the function call"</span>) <span class="hljs-comment"># Extra processing before the function</span>
        func() <span class="hljs-comment"># Call the actual function being decorated</span>
        print(<span class="hljs-string">"After the function call"</span>) <span class="hljs-comment"># Extra processing after the function</span>
    <span class="hljs-keyword">return</span> wrapper <span class="hljs-comment"># Return the nested wrapper function</span>

<span class="hljs-comment"># Function to decorate</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_function</span>():</span>
    print(<span class="hljs-string">"Inside my function"</span>)

<span class="hljs-comment"># Apply decorator on the function</span>
<span class="hljs-meta">@my_decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_function</span>():</span>
    print(<span class="hljs-string">"Inside my function"</span>)

<span class="hljs-comment"># Call the decorated function</span>
my_function()
</code></pre>
<p>A decorator in Python is a function that takes another function as an argument and extends its behavior without modifying it. The decorator function wraps the original function by defining a wrapper function inside of it. This wrapper function executes code before and after calling the original function.</p>
<p>Specifically, when defining a decorator function such as <code>my_decorator</code> in the example, it takes a function as an argument, which we generally call <code>func</code>. This <code>func</code> will be the actual function that is decorated under the hood.</p>
<p>The wrapper function inside <code>my_decorator</code> can execute arbitrary code before and after calling <code>func()</code>, which invokes the original function. When applying <code>@my_decorator</code> before the definition of <code>my_function</code>, it passes <code>my_function</code> as an argument to <code>my_decorator</code>, so func refers to <code>my_function</code> in that context.</p>
<p>The wrapper function then returns the enhanced wrapped function. So now <code>my_function</code> has been decorated by <code>my_decorator</code>. When it is later called, the wrapper code inside <code>my_decorator</code> executes before and after <code>my_function</code> runs. This allows decorators to transparently extend the behavior of a function, without needing to modify the function itself.</p>
<p>And as you'll recall, the original <code>my_function</code> remains unchanged, keeping decorators non-invasive and flexible.</p>
<p>When <code>my_function()</code> is decorated with <code>@my_decorator</code>, it is automatically enhanced. The <code>my_decorator</code> function here returns a wrapper function. This wrapper function gets executed when the <code>my_function()</code> is called now.</p>
<p>First, the wrapper prints <code>"Before the function call"</code> before actually calling the original <code>my_function()</code> function being decorated. Then, after <code>my_function()</code> executes, it prints <code>"After function call"</code>.</p>
<p>So, additional behavior and printed messages are added before and after the <code>my_function()</code> execution in the wrapper, without directly modifying <code>my_function()</code> itself. The decorator allows you to extend <code>my_function()</code> in a transparent way without affecting its core logic, as the wrapper handles the enhanced behavior.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image-109.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Applying a Decorator to a Function</em></p>
<p>So let's start exploring the top 11 practical decorators that every Python developer should know.</p>
<h2 id="heading-log-arguments-and-return-value-of-a-function">Log Arguments and Return Value of a Function</h2>
<p>The Log Arguments and Return Value decorator tracks the input parameters and output of functions. This supports debugging by logging a clear record of data flow through complex operations.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">log_decorator</span>(<span class="hljs-params">original_function</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        print(<span class="hljs-string">f"Calling <span class="hljs-subst">{original_function.__name__}</span> with args: <span class="hljs-subst">{args}</span>, kwargs: <span class="hljs-subst">{kwargs}</span>"</span>)

        <span class="hljs-comment"># Call the original function</span>
        result = original_function(*args, **kwargs)

        <span class="hljs-comment"># Log the return value</span>
        print(<span class="hljs-string">f"<span class="hljs-subst">{original_function.__name__}</span> returned: <span class="hljs-subst">{result}</span>"</span>)

        <span class="hljs-comment"># Return the result</span>
        <span class="hljs-keyword">return</span> result
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-comment"># Example usage</span>
<span class="hljs-meta">@log_decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_product</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-keyword">return</span> x * y

<span class="hljs-comment"># Call the decorated function</span>
result = calculate_product(<span class="hljs-number">10</span>, <span class="hljs-number">20</span>)
print(<span class="hljs-string">"Result:"</span>, result)
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript">Calling calculate_product <span class="hljs-keyword">with</span> args: (<span class="hljs-number">10</span>, <span class="hljs-number">20</span>), <span class="hljs-attr">kwargs</span>: {}
calculate_product returned: <span class="hljs-number">200</span>
<span class="hljs-attr">Result</span>: <span class="hljs-number">200</span>
</code></pre>
<p>In this example, the decorator function is named <code>log_decorator()</code> and accepts a function, <code>original_function</code>, as its argument. Within <code>log_decorator()</code>, a nested function called <code>wrapper()</code> is defined. This <code>wrapper()</code> function is what the decorator returns and effectively replaces the original function.</p>
<p>When the <code>wrapper()</code> function is invoked, it prints logging statements pertaining to the function call. Then it calls the original function, <code>original_function</code>, captures its result, prints the outcome, and returns the result.</p>
<p>The <code>@log_decorator</code> syntax above the <code>calculate_product()</code> function is a Python convention to apply the <code>log_decorator</code> as a decorator to the <code>calculate_product</code> function. So when <code>calculate_product()</code> is invoked, it's actually invoking the <code>wrapper()</code> function returned by <code>log_decorator()</code>. Therefore, <code>log_decorator()</code> acts as a wrapper, introducing logging statements before and after the execution of the original <code>calculate_product()</code> function.</p>
<h3 id="heading-usage-and-applications">Usage and Applications</h3>
<p>This decorator is widely adopted in application development for adding runtime logging without interfering with business logic implementation.</p>
<p>For example, consider a banking application that processes financial transactions. The core transaction processing logic resides in functions like <code>transfer_funds()</code> and <code>accept_payment()</code>. To monitor these transactions, logging can be added by including <code>@log_decorator</code> above each function.</p>
<p>Then when transactions are triggered by calling <code>transfer_funds()</code>, you can print the function name, arguments like the sender, receiver, and amount before the actual transfer. Then after the function returns, you can print the whether the transfer succeeded or failed.</p>
<p>This type of logging with decorators allows you to track transactions without adding any code to core functions like <code>transfer_funds()</code>. The logic stays clean while debuggability and observability improves. Logging messages can be directed to a monitoring dashboard or log analytics system as well.</p>
<h2 id="heading-get-the-execution-time-of-a-function">Get the Execution Time of a Function</h2>
<p>This decorator is your ally in the quest for performance optimization. By measuring and logging the execution time of a function, this decorator facilitates a deep dive into the efficiency of your code, helping you pinpoint bottlenecks and streamline your application's performance.</p>
<p>It's ideal for scenarios where speed is crucial, such as real-time applications or large-scale data processing. And it allows you to identify and address performance bottlenecks systematically.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">measure_execution_time</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">timed_execution</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        start_timestamp = time.time()
        result = func(*args, **kwargs)
        end_timestamp = time.time()
        execution_duration = end_timestamp - start_timestamp
        print(<span class="hljs-string">f"Function <span class="hljs-subst">{func.__name__}</span> took <span class="hljs-subst">{execution_duration:<span class="hljs-number">.2</span>f}</span> seconds to execute"</span>)
        <span class="hljs-keyword">return</span> result
    <span class="hljs-keyword">return</span> timed_execution

<span class="hljs-comment"># Example usage</span>
<span class="hljs-meta">@measure_execution_time</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multiply_numbers</span>(<span class="hljs-params">numbers</span>):</span>
    product = <span class="hljs-number">1</span>
    <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> numbers:
        product *= num
    <span class="hljs-keyword">return</span> product

<span class="hljs-comment"># Call the decorated function</span>
result = multiply_numbers([i <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)])
print(<span class="hljs-string">f"Result: <span class="hljs-subst">{result}</span>"</span>)
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-built_in">Function</span> multiply_numbers took <span class="hljs-number">0.00</span> seconds to execute
<span class="hljs-attr">Result</span>: <span class="hljs-number">362880</span>
</code></pre>
<p>This code showcases a decorator that's designed to measure the execution duration of functions.</p>
<p>The <code>measure_execution_time()</code> decorator takes a function, <code>func</code>, and defines an inner function, <code>timed_execution()</code>, to wrap the original function. Upon invocation, <code>timed_execution()</code> records the start time, calls the original function, records the end time, calculates the duration, and prints it.</p>
<p>The <code>@measure_execution_time</code> syntax applies this decorator to functions below it, such as <code>multiply_numbers()</code>. Consequently, when <code>multiply_numbers()</code> is called, it invokes the <code>timed_execution()</code> wrapper, which logs the duration alongside the function result.</p>
<p>This example illustrates how decorators seamlessly augment existing functions with additional functionality, like timing, without direct modification.</p>
<h3 id="heading-usage-and-applications-1">Usage and Applications</h3>
<p>This decorator is helpful in profiling functions to identify performance bottlenecks in applications. For example, consider an e-commerce site with several backend functions like <code>get_recommendations()</code>, <code>calculate_shipping()</code>, and so on. By decorating them with <code>@measure_execution_time</code>, you can monitor their runtime.</p>
<p>When <code>get_recommendations()</code> is invoked in a user session, the decorator will time its execution duration by recording a start and end timestamp. After execution, it will print the time taken before returning recommendations.</p>
<p>Doing this systematically across applications and analyzing outputs will show you the functions that are taking an unusually long time. The development team can then optimize such functions through caching, parallel processing, and other techniques to improve overall application performance.</p>
<p>Without such timing decorators, finding optimization candidates would require tedious logging code additions. Decorators provide visibility easily without contaminating business logic.</p>
<h2 id="heading-convert-function-return-value-to-a-specified-data-type">Convert Function Return Value to a Specified Data Type</h2>
<p>The Convert Return Value Type decorator enhances data consistency in functions by automatically converting the return value to a specified data type, promoting predictability and preventing unexpected errors. It is particularly useful for downstream processes that require consistent data types, reducing runtime errors.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">convert_to_data_type</span>(<span class="hljs-params">target_type</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">type_converter_decorator</span>(<span class="hljs-params">func</span>):</span>
        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
            result = func(*args, **kwargs)
            <span class="hljs-keyword">return</span> target_type(result)
        <span class="hljs-keyword">return</span> wrapper
    <span class="hljs-keyword">return</span> type_converter_decorator

<span class="hljs-meta">@convert_to_data_type(int)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_values</span>(<span class="hljs-params">a, b</span>):</span>
    <span class="hljs-keyword">return</span> a + b

int_result = add_values(<span class="hljs-number">10</span>, <span class="hljs-number">20</span>)
print(<span class="hljs-string">"Result:"</span>, int_result, type(int_result))

<span class="hljs-meta">@convert_to_data_type(str)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">concatenate_strings</span>(<span class="hljs-params">str1, str2</span>):</span>
    <span class="hljs-keyword">return</span> str1 + str2

str_result = concatenate_strings(<span class="hljs-string">"Python"</span>, <span class="hljs-string">" Decorator"</span>)
print(<span class="hljs-string">"Result:"</span>, str_result, type(str_result))
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript">Result: <span class="hljs-number">30</span> &lt;<span class="hljs-class"><span class="hljs-keyword">class</span> '<span class="hljs-title">int</span>'&gt;
<span class="hljs-title">Result</span>: <span class="hljs-title">Python</span> <span class="hljs-title">Decorator</span> &lt;<span class="hljs-title">class</span> '<span class="hljs-title">str</span>'&gt;</span>
</code></pre>
<p>The above code example shows a decorator that's designed to convert the return value of a function to a specified data type.</p>
<p>The decorator, named <code>convert_to_data_type()</code>, takes the target data type as a parameter and returns a decorator named <code>type_converter_decorator()</code>. Within this decorator, a <code>wrapper()</code> function is defined to call the original function, convert its return value to the target type using <code>target_type()</code>, and subsequently return the converted result.</p>
<p>The syntax <code>@convert_to_data_type(int)</code> that's applied above a function (such as <code>add_values()</code>) utilizes this decorator to convert the return value to an integer. Similarly, for <code>concatenate_strings()</code>, passing <code>str</code> formats the return value as a string.</p>
<p>This example also showcases how decorators seamlessly modify function outputs to desired formats without altering the core logic of the functions.</p>
<h3 id="heading-usage-and-application">Usage and Application</h3>
<p>This return value transformation decorator proves useful in applications where you need to automatically adapt functions to expected data formats.</p>
<p>For instance, you could use it in a weather API that returns temperatures by default in decimal format like 23.456 degrees. But the consumer front-end application expects an integer value to display.</p>
<p>Instead of changing the API function to return an integer, just decorate it with <code>@convert_to_data_type(int)</code>. This will seamlessly convert the decimal temperature to the integer <code>23</code>, in this example, before returning to the client app. Without any API function modification, you've reformatted the return value.</p>
<p>Similarly for backend processing expecting JSON, return values can be converted using the <code>@convert_to_data_type(json)</code> decorator. The core logic stays unchanged while the presentation format adapts based on your use case's needs. This avoids duplication of format handling code across functions.</p>
<p>Decorators externally impose required data representations for seamless integration and reusability across application layers with mismatched formats.</p>
<h2 id="heading-cache-function-results">Cache Function Results</h2>
<p>This decorator optimizes performance by storing and retrieving function results, eliminating redundant computations for repeated inputs, and improving application responsiveness, especially for time-consuming computations.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cached_result_decorator</span>(<span class="hljs-params">func</span>):</span>
    result_cache = {}

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        cache_key = (*args, *kwargs.items())

        <span class="hljs-keyword">if</span> cache_key <span class="hljs-keyword">in</span> result_cache:
            <span class="hljs-keyword">return</span> <span class="hljs-string">f"[FROM CACHE] <span class="hljs-subst">{result_cache[cache_key]}</span>"</span>

        result = func(*args, **kwargs)
        result_cache[cache_key] = result

        <span class="hljs-keyword">return</span> result

    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-comment"># Example usage</span>

<span class="hljs-meta">@cached_result_decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multiply_numbers</span>(<span class="hljs-params">a, b</span>):</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">f"Product = <span class="hljs-subst">{a * b}</span>"</span>

<span class="hljs-comment"># Call the decorated function multiple times</span>
print(multiply_numbers(<span class="hljs-number">4</span>, <span class="hljs-number">5</span>))  <span class="hljs-comment"># Calculation is performed</span>
print(multiply_numbers(<span class="hljs-number">4</span>, <span class="hljs-number">5</span>))  <span class="hljs-comment"># Result is retrieved from cache</span>
print(multiply_numbers(<span class="hljs-number">5</span>, <span class="hljs-number">7</span>))  <span class="hljs-comment"># Calculation is performed</span>
print(multiply_numbers(<span class="hljs-number">5</span>, <span class="hljs-number">7</span>))  <span class="hljs-comment"># Result is retrieved from cache</span>
print(multiply_numbers(<span class="hljs-number">-3</span>, <span class="hljs-number">7</span>))  <span class="hljs-comment"># Calculation is performed</span>
print(multiply_numbers(<span class="hljs-number">-3</span>, <span class="hljs-number">7</span>))  <span class="hljs-comment"># Result is retrieved from cache</span>
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript">Product = <span class="hljs-number">20</span>
[FROM CACHE] Product = <span class="hljs-number">20</span>
Product = <span class="hljs-number">35</span>
[FROM CACHE] Product = <span class="hljs-number">35</span>
Product = <span class="hljs-number">-21</span>
[FROM CACHE] Product = <span class="hljs-number">-21</span>
</code></pre>
<p>This code sample showcases a decorator that's designed to cache and reuse function call results efficiently.</p>
<p>The <code>cached_result_decorator()</code> function takes another function and returns a wrapper. Within this wrapper, a cache dictionary (<code>result_cache</code>) stores unique call parameters and their corresponding results.</p>
<p>Before executing the actual function, the <code>wrapper()</code> checks if the result for the current parameters is already in the cache. If so, it retrieves and returns the cached result – otherwise, it calls the function, stores the result in the cache, and returns it.</p>
<p>The <code>@cached_result_decorator</code> syntax applies this caching logic to any function, such as <code>multiply_numbers()</code>. This ensures that, upon subsequent calls with the same arguments, the cached result is reused, preventing redundant calculations.</p>
<p>In essence, the decorator enhances functionality by optimizing performance through result caching.</p>
<h3 id="heading-usage-and-applications-2">Usage and Applications</h3>
<p>Caching decorators like this are extremely useful in application development for optimizing performance of repetitive function calls.</p>
<p>For example, consider a recommendation engine calling predictive model functions to generate user suggestions. <code>get_user_recommendations()</code> prepares the input data and feeds into the model for every user request.Instead of re-running computations, it can be decorated with <code>@cached_result_decorator</code> to introduce caching layer.</p>
<p>Now the first time unique user parameters are passed, the model runs and the result caches. Subsequent calls with the same inputs directly return the cached model outputs, skipping the model recalculation.</p>
<p>This drastically improves latency for responding to user requests by avoiding duplicate model inferences. You can monitor cache hit rates to justify scaling down model server infrastructure costs.</p>
<p>Decoupling such optimization concerns through caching decorators rather than mixing them inside function logic improves modularity, readability and allows rapid performance gains. Caches will be configured, invalidated separately without intruding business functions.</p>
<h2 id="heading-validate-function-arguments-based-on-condition">Validate Function Arguments Based on Condition</h2>
<p>This one checks if input arguments meet predefined criteria before execution, enhancing function reliability and preventing unexpected behavior. It is useful for parameters requiring positive integers or non-empty strings.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">check_condition_positive</span>(<span class="hljs-params">value</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">argument_validator</span>(<span class="hljs-params">func</span>):</span>
        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">validate_and_calculate</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
            <span class="hljs-keyword">if</span> value(*args, **kwargs):
                <span class="hljs-keyword">return</span> func(*args, **kwargs)
            <span class="hljs-keyword">else</span>:
                <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Invalid arguments passed to the function"</span>)
        <span class="hljs-keyword">return</span> validate_and_calculate
    <span class="hljs-keyword">return</span> argument_validator

<span class="hljs-meta">@check_condition_positive(lambda x: x &gt; 0)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">compute_cubed_result</span>(<span class="hljs-params">number</span>):</span>
    <span class="hljs-keyword">return</span> number ** <span class="hljs-number">3</span>

print(compute_cubed_result(<span class="hljs-number">5</span>))  <span class="hljs-comment"># Output: 125</span>
print(compute_cubed_result(<span class="hljs-number">-2</span>))  <span class="hljs-comment"># Raises ValueError: Invalid arguments passed to the function</span>
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-number">125</span>Traceback (most recent call last):

  File <span class="hljs-string">"C:\\\\Program Files\\\\Sublime Text 3\\\\test.py"</span>, line <span class="hljs-number">16</span>, <span class="hljs-keyword">in</span> &lt;<span class="hljs-built_in">module</span>&gt;
    print(compute_cubed_result(<span class="hljs-number">-2</span>))  # Raises ValueError: Invalid <span class="hljs-built_in">arguments</span> passed to the <span class="hljs-function"><span class="hljs-keyword">function</span>
  <span class="hljs-title">File</span> "<span class="hljs-title">C</span>:\\\\<span class="hljs-title">Program</span> <span class="hljs-title">Files</span>\\\\<span class="hljs-title">Sublime</span> <span class="hljs-title">Text</span> 3\\\\<span class="hljs-title">test</span>.<span class="hljs-title">py</span>", <span class="hljs-title">line</span> 7, <span class="hljs-title">in</span> <span class="hljs-title">validate_and_calculate</span>
    <span class="hljs-title">raise</span> <span class="hljs-title">ValueError</span>(<span class="hljs-params"><span class="hljs-string">"Invalid arguments passed to the function"</span></span>)
<span class="hljs-title">ValueError</span>: <span class="hljs-title">Invalid</span> <span class="hljs-title">arguments</span> <span class="hljs-title">passed</span> <span class="hljs-title">to</span> <span class="hljs-title">the</span> <span class="hljs-title">function</span></span>
</code></pre>
<p>This code showcases how you can implement a decorator for validating function arguments.</p>
<p>The <code>check_condition_positive()</code> is a decorator factory that generates an <code>argument_validator()</code> decorator. This validator, when applied with <code>@check_condition_positive()</code> above the <code>compute_cubed_result()</code> function, checks if the condition (in this case, that the argument should be greater than 0) holds true for the passed arguments.</p>
<p>If the condition is met, the decorated function is executed – otherwise, a <code>ValueError</code> exception is raised.</p>
<p>This succinct example illustrates how decorators serve as a mechanism for validating function arguments before their execution, ensuring adherence to specified conditions.</p>
<h3 id="heading-usage-and-applications-3">Usage and Applications</h3>
<p>Such parameter validation decorators are extremely useful in applications to help enforce business rules, security constraints, and so on.</p>
<p>For example, an insurance claims processing system would have a function <code>process_claim()</code> that takes details like claim id, approver name, and so on. Certain business rules dictate who can approve claims.</p>
<p>Rather than cluttering the function logic itself, you can decorate it with <code>@check_condition_positive()</code> which validates if the approver role matches the claim amount. If a junior agent tries approving a large claim (thus violating the rules), this decorator would catch it by raising exception even before <code>process_claim()</code> executes.</p>
<p>Similarly, input data validation constraints for security and compliance can be imposed without touching individual functions. Decorators externally ensure that violated arguments never reach application risks.</p>
<p>Common validation patterns should be reused across multiple functions. This improves security and promotes separation of concerns by isolating constraints from core logic flow in a modular way.</p>
<h2 id="heading-retry-a-function-multiple-times-on-failure">Retry a Function Multiple Times on Failure</h2>
<p>This decorator comes handy when you want to automatically retry a function after failure, enhancing its resilience in situations involving transient failures. It is used for external services or network requests prone to intermittent failures.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sqlite3
<span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">retry_on_failure</span>(<span class="hljs-params">max_attempts, retry_delay=<span class="hljs-number">1</span></span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorator</span>(<span class="hljs-params">func</span>):</span>
        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
            <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(max_attempts):
                <span class="hljs-keyword">try</span>:
                    result = func(*args, **kwargs)
                    <span class="hljs-keyword">return</span> result
                <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> error:
                    print(<span class="hljs-string">f"Error occurred: <span class="hljs-subst">{error}</span>. Retrying..."</span>)
                    time.sleep(retry_delay)
            <span class="hljs-keyword">raise</span> Exception(<span class="hljs-string">"Maximum attempts exceeded. Function failed."</span>)

        <span class="hljs-keyword">return</span> wrapper
    <span class="hljs-keyword">return</span> decorator

<span class="hljs-meta">@retry_on_failure(max_attempts=3, retry_delay=2)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">establish_database_connection</span>():</span>
    connection = sqlite3.connect(<span class="hljs-string">"example.db"</span>)
    db_cursor = connection.cursor()
    db_cursor.execute(<span class="hljs-string">"SELECT * FROM users"</span>)
    query_result = db_cursor.fetchall()
    db_cursor.close()
    connection.close()
    <span class="hljs-keyword">return</span> query_result

<span class="hljs-keyword">try</span>:
    retrieved_data = establish_database_connection()
    print(<span class="hljs-string">"Data retrieved successfully:"</span>, retrieved_data)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> error_message:
    print(<span class="hljs-string">f"Failed to establish database connection: <span class="hljs-subst">{error_message}</span>"</span>)
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-built_in">Error</span> occurred: no such table: users. Retrying...
Error occurred: no such table: users. Retrying...
Error occurred: no such table: users. Retrying...
Failed to establish database connection: Maximum attempts exceeded. Function failed.
</code></pre>
<p>This example introduces a decorator that's designed for retrying function executions in the event of failures. It has a specified maximum attempt count and delay between retries.</p>
<p>The <code>retry_on_failure()</code> is a decorator factory, taking parameters for maximum retry count and delay, and returning a <code>decorator()</code> that manages the retry logic.</p>
<p>Within the <code>wrapper()</code> function, the decorated function undergoes execution in a loop, attempting a specified maximum number of times.</p>
<p>In case of an exception, it prints an error message, introduces a delay specified by <code>retry_delay</code>, and retries. If all attempts fail, it raises an exception indicating that the maximum attempts have been exceeded.</p>
<p>The <code>@retry_on_failure()</code> applied above <code>establish_database_connection()</code> integrates this retry logic, allowing for up to 3 retries with a 2-second delay between each attempt in case the database connection encounters failures.</p>
<p>This demonstrates the utility of decorators in seamlessly incorporating retry capabilities without altering the core function code.</p>
<h3 id="heading-usage-and-application-1">Usage and Application</h3>
<p>This retry decorator can prove extremely useful in application development for adding resilience against temporary or intermittent errors.</p>
<p>For instance, consider a flight booking app that calls a payment gateway API <code>process_payment()</code> to handle customer transactions. Sometimes network blips or high loads at payment provider end could cause transient errors in API response.</p>
<p>Rather than directly showing failures to customers, the <code>process_payment()</code> function can be decorated with <code>@retry_on_failure</code> to handle such scenarios implicitly. Now when a payment fails once, it will seamlessly retry sending the request up to 3 times before finally reporting the error if it persists.</p>
<p>This provides shielding from temporary hiccups without exposing users to unreliable infrastructure behavior directly.The application also remains available reliably even if dependent services fail occasionally.</p>
<p>The decorator helps confine the retry logic neatly without spreading it across the API's code. Failures beyond the app's control are handled gracefully rather than directly impacting users by application faults. This demonstrates how decorators lend better resilience without complicating business logic.</p>
<h2 id="heading-enforce-rate-limits-on-a-function">Enforce Rate Limits on a Function</h2>
<p>By controlling the frequency of functions called, the Enforce Rate Limits decorator ensures effective resource management and guards against misuse. It is especially helpful in scenarios like API misuse or resource conservation where restricting function calls is essential.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">rate_limiter</span>(<span class="hljs-params">max_allowed_calls, reset_period_seconds</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorate_rate_limited_function</span>(<span class="hljs-params">original_function</span>):</span>
        calls_count = <span class="hljs-number">0</span>
        last_reset_time = time.time()

        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper_function</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
            <span class="hljs-keyword">nonlocal</span> calls_count, last_reset_time
            elapsed_time = time.time() - last_reset_time

            <span class="hljs-comment"># If the elapsed time is greater than the reset period, reset the call count</span>
            <span class="hljs-keyword">if</span> elapsed_time &gt; reset_period_seconds:
                calls_count = <span class="hljs-number">0</span>
                last_reset_time = time.time()

            <span class="hljs-comment"># Check if the call count has reached the maximum allowed limit</span>
            <span class="hljs-keyword">if</span> calls_count &gt;= max_allowed_calls:
                <span class="hljs-keyword">raise</span> Exception(<span class="hljs-string">"Rate limit exceeded. Please try again later."</span>)

            <span class="hljs-comment"># Increment the call count</span>
            calls_count += <span class="hljs-number">1</span>

            <span class="hljs-comment"># Call the original function</span>
            <span class="hljs-keyword">return</span> original_function(*args, **kwargs)

        <span class="hljs-keyword">return</span> wrapper_function
    <span class="hljs-keyword">return</span> decorate_rate_limited_function

<span class="hljs-comment"># Allowing a maximum of 6 API calls within 10 seconds.</span>
<span class="hljs-meta">@rate_limiter(max_allowed_calls=6, reset_period_seconds=10)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">make_api_call</span>():</span>
    print(<span class="hljs-string">"API call executed successfully..."</span>)

<span class="hljs-comment"># Make API calls</span>
<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(<span class="hljs-number">8</span>):
    <span class="hljs-keyword">try</span>:
        make_api_call()
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> error:
        print(<span class="hljs-string">f"Error occurred: <span class="hljs-subst">{error}</span>"</span>)
time.sleep(<span class="hljs-number">10</span>)
make_api_call()
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript">API call executed successfully...
API call executed successfully...
API call executed successfully...
API call executed successfully...
API call executed successfully...
API call executed successfully...
Error occurred: Rate limit exceeded. Please <span class="hljs-keyword">try</span> again later.
Error occurred: Rate limit exceeded. Please <span class="hljs-keyword">try</span> again later.
API call executed successfully...
</code></pre>
<p>This code showcases the implementation of a rate-limiting mechanism for function calls using a decorator.</p>
<p>The <code>rate_limiter()</code> function, specified with maximum calls and a period in seconds to reset the count, serves as the core of the rate-limiting logic. The decorator, <code>decorate_rate_limited_function()</code>, employs a wrapper to manage the rate limits by resetting the count if the period has elapsed. It checks if the count has reached the maximum allowed, and then either raises an exception or increments the count and executes the function accordingly.</p>
<p>Applied to <code>make_api_call()</code> using <code>@rate_limiter()</code>, it restricts the function to six calls within any 10-second period. This introduces rate limiting without changing the function logic, ensuring that calls adhere to limits and preventing excessive use within set intervals.</p>
<h3 id="heading-usage-and-application-2">Usage and Application</h3>
<p>Rate limiting decorators like this are very useful in application development for controlling usage of APIs and preventing abuse.</p>
<p>For instance, a travel booking application may rely on third party Flight Search API for checking live seat availability across airlines. While most usage is legitimate, some users could potentially call this API excessively, degrading overall service performance.</p>
<p>By decorating the API integration module like <code>@rate_limiter(100, 60)</code>, the application can restrict excessive calls internally, too. This would limit the booking module to make only 100 Flight API calls per minute. Additional calls get rejected directly through the decorator without even reaching actual API.</p>
<p>This saves downstream service from overuse enabling fairer distribution of capacity for general application functionality.</p>
<p>Decorators provide easy rate control for both internal and external facing APIs without changing functional code. This means you don't have to account for usage quotas while safeguarding services, infrastructure, and bounding adoption risk. And it's all thanks to application-side controls using wrappers.</p>
<h2 id="heading-handle-exceptions-and-provide-default-response">Handle Exceptions and Provide Default Response</h2>
<p>The Handle Exceptions decorator is a safety net for functions, gracefully handling exceptions and providing default responses when they occur. It shields the application from crashing due to unforeseen circumstances, ensuring smooth operation.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">handle_exceptions</span>(<span class="hljs-params">default_response_msg</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">exception_handler_decorator</span>(<span class="hljs-params">func</span>):</span>
        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorated_function</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
            <span class="hljs-keyword">try</span>:
                <span class="hljs-comment"># Call the original function</span>
                <span class="hljs-keyword">return</span> func(*args, **kwargs)
            <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> error:
                <span class="hljs-comment"># Handle the exception and provide the default response</span>
                print(<span class="hljs-string">f"Exception occurred: <span class="hljs-subst">{error}</span>"</span>)
                <span class="hljs-keyword">return</span> default_response_msg
        <span class="hljs-keyword">return</span> decorated_function
    <span class="hljs-keyword">return</span> exception_handler_decorator

<span class="hljs-comment"># Example usage</span>
<span class="hljs-meta">@handle_exceptions(default_response_msg="An error occurred!")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">divide_numbers_safely</span>(<span class="hljs-params">dividend, divisor</span>):</span>
    <span class="hljs-keyword">return</span> dividend / divisor

<span class="hljs-comment"># Call the decorated function</span>
result = divide_numbers_safely(<span class="hljs-number">7</span>, <span class="hljs-number">0</span>)  <span class="hljs-comment"># This will raise a ZeroDivisionError</span>
print(<span class="hljs-string">"Result:"</span>, result)
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript">Exception occurred: division by zero
<span class="hljs-attr">Result</span>: An error occurred!
</code></pre>
<p>This code showcases exception handling in functions using decorators.</p>
<p>The <code>handle_exceptions()</code> decorator factory, accepting a default response, produces <code>exception_handler_decorator()</code>. This decorator, when applied to functions, attempts to execute the original function. If an exception arises, it prints error details, and returns the specified default response.</p>
<p>The <code>@handle_exceptions()</code> syntax above a function incorporates this exception-handling logic. For instance, in <code>divide_numbers_safely()</code>, division by zero triggers an exception, which the decorator catches, preventing a crash and returning the default "An error occurred!" response.</p>
<p>Essentially, these decorators adeptly capture exceptions in functions, providing a seamless means of incorporating handling logic and preventing crashes.</p>
<h3 id="heading-usage-and-applications-4">Usage and Applications</h3>
<p>Exception handling decorators greatly simplify application error management and help hide unreliable behavior from users.</p>
<p>For example, an e-commerce website may rely on payment, inventory, and shipping services to complete orders. Instead of complex exception blocks everywhere, core order processing function like <code>place_order()</code> can be decorated to achieve resilience.</p>
<p>The <code>@handle_exceptions</code> decorator applied above it would absorb any third party service outage or intermittent issue during order finalization. On exception, it logs errors for debugging while serving a graceful "Order failed, please try again later" message to the customer. This avoids expose complex failure root causes like payment timeouts to end user.</p>
<p>Decorators shield customers from unreliable service issues without changing business code. They provide friendly default responses when errors happen. This improves customer experience</p>
<p>Also, decorators give developers visibility into those errors behind the scenes. So they can focus on systematically fixing the root causes of failures. This separation of concerns through decorators reduces complexity. Customers see more reliability, and you get actionable insights into faults – all while keeping business logic untouched.</p>
<h2 id="heading-enforce-type-checking-on-function-arguments">Enforce Type Checking on Function Arguments</h2>
<p>The Enforce Type Checking decorator ensures data integrity by verifying function arguments conform to specified data types, preventing type-related errors, and promoting code reliability. It is particularly useful in situations where strict data type adherence is crucial.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> inspect

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">enforce_type_checking</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">type_checked_wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        <span class="hljs-comment"># Get the function signature and parameter names</span>
        function_signature = inspect.signature(func)
        function_parameters = function_signature.parameters

        <span class="hljs-comment"># Iterate over the positional arguments</span>
        <span class="hljs-keyword">for</span> i, arg_value <span class="hljs-keyword">in</span> enumerate(args):
            parameter_name = list(function_parameters.keys())[i]
            parameter_type = function_parameters[parameter_name].annotation
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> isinstance(arg_value, parameter_type):
                <span class="hljs-keyword">raise</span> TypeError(<span class="hljs-string">f"Argument '<span class="hljs-subst">{parameter_name}</span>' must be of type '<span class="hljs-subst">{parameter_type.__name__}</span>'"</span>)

        <span class="hljs-comment"># Iterate over the keyword arguments</span>
        <span class="hljs-keyword">for</span> keyword_name, arg_value <span class="hljs-keyword">in</span> kwargs.items():
            parameter_type = function_parameters[keyword_name].annotation
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> isinstance(arg_value, parameter_type):
                <span class="hljs-keyword">raise</span> TypeError(<span class="hljs-string">f"Argument '<span class="hljs-subst">{keyword_name}</span>' must be of type '<span class="hljs-subst">{parameter_type.__name__}</span>'"</span>)

        <span class="hljs-comment"># Call the original function</span>
        <span class="hljs-keyword">return</span> func(*args, **kwargs)

    <span class="hljs-keyword">return</span> type_checked_wrapper

<span class="hljs-comment"># Example usage</span>
<span class="hljs-meta">@enforce_type_checking</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multiply_numbers</span>(<span class="hljs-params">factor_1: int, factor_2: int</span>) -&gt; int:</span>
    <span class="hljs-keyword">return</span> factor_1 * factor_2

<span class="hljs-comment"># Call the decorated function</span>
result = multiply_numbers(<span class="hljs-number">5</span>, <span class="hljs-number">7</span>)  <span class="hljs-comment"># No type errors, returns 35</span>
print(<span class="hljs-string">"Result:"</span>, result)

result = multiply_numbers(<span class="hljs-string">"5"</span>, <span class="hljs-number">7</span>)  <span class="hljs-comment"># Type error: 'factor_1' must be of type 'int'</span>
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript">Result:Traceback (most recent call last):
  File <span class="hljs-string">"C:\\\\Program Files\\\\Sublime Text 3\\\\test.py"</span>, line <span class="hljs-number">36</span>, <span class="hljs-keyword">in</span> &lt;<span class="hljs-built_in">module</span>&gt;
 <span class="hljs-number">35</span>
    result = multiply_numbers(<span class="hljs-string">"5"</span>, <span class="hljs-number">7</span>)  # Type error: <span class="hljs-string">'factor_1'</span> must be <span class="hljs-keyword">of</span> type <span class="hljs-string">'int'</span>
  File <span class="hljs-string">"C:\\\\Program Files\\\\Sublime Text 3\\\\test.py"</span>, line <span class="hljs-number">14</span>, <span class="hljs-keyword">in</span> type_checked_wrapper
    raise <span class="hljs-built_in">TypeError</span>(f<span class="hljs-string">"Argument '{parameter_name}' must be of type '{parameter_type.__name__}'"</span>)
<span class="hljs-attr">TypeError</span>: Argument <span class="hljs-string">'factor_1'</span> must be <span class="hljs-keyword">of</span> type <span class="hljs-string">'int'</span>
</code></pre>
<p>The <code>enforce_type_checking</code> decorator validates whether the arguments passed to a function match the specified type annotations.</p>
<p>Inside the <code>type_checked_wrapper</code>, it examines the signature of the decorated function, retrieves parameter names and type annotations, and ensures that the provided arguments align with the expected types. This includes checking positional arguments against their order, and keyword arguments against parameter names. If a type mismatch is detected, a TypeError is raised.</p>
<p>This decorator is exemplified by its application to the <code>multiply_numbers</code> function, where arguments are annotated as integers. Attempting to pass a string results in an exception, while passing integers executes the function without issues. This type checking is enforced without altering the original function body.</p>
<h3 id="heading-usage-and-applications-5">Usage and Applications</h3>
<p>Type checking decorators are applied to detect issues early and improve reliability. For example, consider a web application backend with a data access layer function <code>get_user_data()</code> annotated to expect integer user IDs. Its queries would fail if string IDs flow into it from frontend code.</p>
<p>Rather than add explicit checks and raise exceptions locally, you can use this decorator. Now any upstream or consumer code passing invalid types will be automatically caught during function execution. The decorator examines annotations versus argument types and throws errors accordingly before reaching the database layer.</p>
<p>This runtime protection for components through decorators ensures that only valid data shapes flow across layers, preventing obscure errors. Type safety is imposed without extra checks cluttering cleaner logic.</p>
<h2 id="heading-measure-memory-usage-of-a-function">Measure Memory Usage of a Function</h2>
<p>When it comes to large dataset-intensive applications or resource-constrained environments, the Measure Memory Usage Decorator is a memory detective that offers insights into function memory consumption. It does this by optimising memory usage.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> tracemalloc

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">measure_memory_usage</span>(<span class="hljs-params">target_function</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        tracemalloc.start()

        <span class="hljs-comment"># Call the original function</span>
        result = target_function(*args, **kwargs)

        snapshot = tracemalloc.take_snapshot()
        top_stats = snapshot.statistics(<span class="hljs-string">"lineno"</span>)

        <span class="hljs-comment"># Print the top memory-consuming lines</span>
        print(<span class="hljs-string">f"Memory usage of <span class="hljs-subst">{target_function.__name__}</span>:"</span>)
        <span class="hljs-keyword">for</span> stat <span class="hljs-keyword">in</span> top_stats[:<span class="hljs-number">5</span>]:
            print(stat)

        <span class="hljs-comment"># Return the result</span>
        <span class="hljs-keyword">return</span> result

    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-comment"># Example usage</span>
<span class="hljs-meta">@measure_memory_usage</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_factorial_recursive</span>(<span class="hljs-params">number</span>):</span>
    <span class="hljs-keyword">if</span> number == <span class="hljs-number">0</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> number * calculate_factorial_recursive(number - <span class="hljs-number">1</span>)

<span class="hljs-comment"># Call the decorated function</span>
result_factorial = calculate_factorial_recursive(<span class="hljs-number">3</span>)
print(<span class="hljs-string">"Factorial:"</span>, result_factorial)
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript">Memory usage <span class="hljs-keyword">of</span> calculate_factorial_recursive:
C:\\\\Program Files\\\\Sublime Text <span class="hljs-number">3</span>\\\\test.py:<span class="hljs-number">29</span>: size=<span class="hljs-number">1552</span> B, count=<span class="hljs-number">6</span>, average=<span class="hljs-number">259</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Sublime Text <span class="hljs-number">3</span>\\\\test.py:<span class="hljs-number">8</span>: size=<span class="hljs-number">896</span> B, count=<span class="hljs-number">3</span>, average=<span class="hljs-number">299</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Sublime Text <span class="hljs-number">3</span>\\\\test.py:<span class="hljs-number">10</span>: size=<span class="hljs-number">416</span> B, count=<span class="hljs-number">1</span>, average=<span class="hljs-number">416</span> B
Memory usage <span class="hljs-keyword">of</span> calculate_factorial_recursive:
C:\\\\Program Files\\\\Sublime Text <span class="hljs-number">3</span>\\\\test.py:<span class="hljs-number">29</span>: size=<span class="hljs-number">1552</span> B, count=<span class="hljs-number">6</span>, average=<span class="hljs-number">259</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">226</span>: size=<span class="hljs-number">880</span> B, count=<span class="hljs-number">3</span>, average=<span class="hljs-number">293</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Sublime Text <span class="hljs-number">3</span>\\\\test.py:<span class="hljs-number">8</span>: size=<span class="hljs-number">832</span> B, count=<span class="hljs-number">2</span>, average=<span class="hljs-number">416</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">173</span>: size=<span class="hljs-number">800</span> B, count=<span class="hljs-number">2</span>, average=<span class="hljs-number">400</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">505</span>: size=<span class="hljs-number">592</span> B, count=<span class="hljs-number">2</span>, average=<span class="hljs-number">296</span> B
Memory usage <span class="hljs-keyword">of</span> calculate_factorial_recursive:
C:\\\\Program Files\\\\Sublime Text <span class="hljs-number">3</span>\\\\test.py:<span class="hljs-number">29</span>: size=<span class="hljs-number">1440</span> B, count=<span class="hljs-number">4</span>, average=<span class="hljs-number">360</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">535</span>: size=<span class="hljs-number">1240</span> B, count=<span class="hljs-number">3</span>, average=<span class="hljs-number">413</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">67</span>: size=<span class="hljs-number">1216</span> B, count=<span class="hljs-number">19</span>, average=<span class="hljs-number">64</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">193</span>: size=<span class="hljs-number">1104</span> B, count=<span class="hljs-number">23</span>, average=<span class="hljs-number">48</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">226</span>: size=<span class="hljs-number">880</span> B, count=<span class="hljs-number">3</span>, average=<span class="hljs-number">293</span> B
Memory usage <span class="hljs-keyword">of</span> calculate_factorial_recursive:
C:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">558</span>: size=<span class="hljs-number">1416</span> B, count=<span class="hljs-number">29</span>, average=<span class="hljs-number">49</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">67</span>: size=<span class="hljs-number">1408</span> B, count=<span class="hljs-number">22</span>, average=<span class="hljs-number">64</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Sublime Text <span class="hljs-number">3</span>\\\\test.py:<span class="hljs-number">29</span>: size=<span class="hljs-number">1392</span> B, count=<span class="hljs-number">3</span>, average=<span class="hljs-number">464</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">535</span>: size=<span class="hljs-number">1240</span> B, count=<span class="hljs-number">3</span>, average=<span class="hljs-number">413</span> B
<span class="hljs-attr">C</span>:\\\\Program Files\\\\Python310\\\\lib\\\\tracemalloc.py:<span class="hljs-number">226</span>: size=<span class="hljs-number">832</span> B, count=<span class="hljs-number">2</span>, average=<span class="hljs-number">416</span> B
<span class="hljs-attr">Factorial</span>: <span class="hljs-number">6</span>
</code></pre>
<p>This code showcases a decorator, <code>measure_memory_usage</code>, designed to measure the memory consumption of functions.</p>
<p>The decorator, when applied, initiates memory tracking before the original function is called. Once the function completes its execution, a memory snapshot is taken and the top 5 lines consuming the most memory are printed.</p>
<p>Illustrated through the example of <code>calculate_factorial_recursive()</code>, the decorator allows you to monitor memory usage without altering the function itself, offering valuable insights for optimization purposes.</p>
<p>In essence, it provides a straightforward means to assess and analyze the memory consumption of any function during its runtime.</p>
<h3 id="heading-usage-and-applications-6">Usage and Applications</h3>
<p>Memory measurement decorators like these are extremely valuable in application development for identifying and troubleshooting memory bloat or leak issues.</p>
<p>For example, consider a data streaming pipeline with critical ETL components like <code>transform_data()</code> that processes large volumes of information. Though the process seems fine during regular loads, high volume data like Black Friday sales could cause excessive memory usage and crashes.</p>
<p>Rather than manual debugging, decorating processors like @measure_memory_usage can reveal useful insights. It will print the top memory intensive lines during peak data flow without any code change.</p>
<p>You should aim to pinpoint specific stages eating up memory rapidly and address through better algorithms or optimization.</p>
<p>Such decorators help bake diagnostics perspectives across critical paths to recognize abnormal consumption trends early. Instead of delayed production issues, problems can be preemptively identified through profiling before release. They reduce debugging headaches and minimize runtime failures via easier instrumentation for memory tracking.</p>
<h2 id="heading-cache-function-results-with-expiration-time">Cache Function Results with Expiration Time</h2>
<p>Specifically designed for outdated data, the Cache Function Results with Expiration Time Decorator is a tool that combines caching with a time-based expiration feature to make sure that cached data is regularly refreshed to prevent staleness and maintain relevance.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cached_function_with_expiry</span>(<span class="hljs-params">expiry_time</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorator</span>(<span class="hljs-params">original_function</span>):</span>
        cache = {}

        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
            key = (*args, *kwargs.items())

            <span class="hljs-keyword">if</span> key <span class="hljs-keyword">in</span> cache:
                cached_value, cached_timestamp = cache[key]

                <span class="hljs-keyword">if</span> time.time() - cached_timestamp &lt; expiry_time:
                    <span class="hljs-keyword">return</span> <span class="hljs-string">f"[CACHED] - <span class="hljs-subst">{cached_value}</span>"</span>

            result = original_function(*args, **kwargs)
            cache[key] = (result, time.time())

            <span class="hljs-keyword">return</span> result

        <span class="hljs-keyword">return</span> wrapper

    <span class="hljs-keyword">return</span> decorator

<span class="hljs-comment"># Example usage</span>

<span class="hljs-meta">@cached_function_with_expiry(expiry_time=5)  # Cache expiry time set to 5 seconds</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_product</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">f"PRODUCT - <span class="hljs-subst">{x * y}</span>"</span>

<span class="hljs-comment"># Call the decorated function multiple times</span>
print(calculate_product(<span class="hljs-number">23</span>, <span class="hljs-number">5</span>))  <span class="hljs-comment"># Calculation is performed</span>
print(calculate_product(<span class="hljs-number">23</span>, <span class="hljs-number">5</span>))  <span class="hljs-comment"># Result is retrieved from cache</span>
time.sleep(<span class="hljs-number">5</span>)
print(calculate_product(<span class="hljs-number">23</span>, <span class="hljs-number">5</span>))  <span class="hljs-comment"># Calculation is performed (cache expired)</span>
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-javascript">PRODUCT - <span class="hljs-number">115</span>
[CACHED] - PRODUCT - <span class="hljs-number">115</span>
PRODUCT - <span class="hljs-number">115</span>
</code></pre>
<p>This code showcases a caching decorator that has an automatic cache expiration time.</p>
<p>The function <code>cached_function_with_expiry()</code> generates a decorator that, when applied, utilizes a dictionary called <code>cache</code> to store function results and their corresponding timestamps. The <code>wrapper()</code> function checks if the result for the current arguments is in the cache. If present and within the expiry time, it returns the cached result – otherwise, it calls the function.</p>
<p>Illustrated using <code>calculate_product()</code>, the decorator initially calculates and caches the result. Subsequent calls retrieve the cached result until the expiry period, at which point the cache is refreshed through a recalculation.</p>
<p>In essence, this implementation prevents redundant calculations while automatically refreshing results after the specified expiry period.</p>
<h3 id="heading-usage-and-applications-7">Usage and Applications</h3>
<p>Automatic cache expiry decorators are very useful in application development for optimizing performance of data fetching modules.</p>
<p>For example, consider a travel website that calls backend API <code>get_flight_prices()</code> to show live prices to users. While caches reduce calls to expensive flight data sources, static caching leads to displaying stale prices.</p>
<p>Instead, you can use <code>@cached_function_with_expiry(60)</code> to auto-refresh every minute. Now, the first user call fetches live prices and caches them, while subsequent requests in a 60s window efficiently reuse the cached pricing. But caches automatically invalidate after the expiry period to guarantee fresh data.</p>
<p>This allows your to optimize flows without worrying about corner cases related to outdated representations. This decorator handles the situation reliably, keeping caches in sync with upstream changes through configurable refreshing. There's zero redundancy of recalculations, and you still get the best possible updated information to end users. Common caching patterns get packaged conveniently for reuse across codebase with customized expiry rules.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Python decorators continue to see widespread usage in application development for cleanly inserting common cross-cutting concerns. Authentications, monitoring, and restrictions are some standard examples of use cases that use decorators in frameworks like Django and Flask.</p>
<p>The popularity of web APIs has also lead to common adoption of rate limiting and caching decorators for performance.</p>
<p>Decorators have actually been around since early Python releases. Guido van Rossum wrote about enhancement with decorators in a 1990 paper on Python. Later when function decorators syntax stabilized in Python 2.4 in 2004, it opened the doors for elegant solutions through oriented programming. From web to data science, they continue to empower abstraction and modularity across Python domains.</p>
<p>The examples in this handbook only scratch the surface of what custom tailored decorators can enable. Based on any specific objective like security, throttling user requests, transparent encryption, and so on, you can create innovative decorators to address your needs. Structuring logic processing pipelines using a composition of specialized single-responsibility decorators also encourages reuse over redundancy.</p>
<p>Understanding decorators not only improves development skills but unlocks ways to dictate program behaviour flexibly. I encourage you to assess common needs across your codebases that can be abstracted into standalone decorators. With some practice, it becomes easy to spot cross-cutting concerns and extend functions efficiently without breaking a sweat.</p>
<p>If you liked this lesson and would like to explore more insightful tech content, including Python, Django, and System Design reads, check out my <a target="_blank" href="https://atharvashah.netlify.app">Blog</a>. You can also view my projects with proof of work on <a target="_blank" href="https://github.com/HighnessAtharva">GitHub</a> and connect with me on <a target="_blank" href="https://www.linkedin.com/in/atharva-shah-5873a2111/">LinkedIn</a> for a chat.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Python Decorators Explained For Beginners ]]>
                </title>
                <description>
                    <![CDATA[ By Roy Chng In the world of Python programming, decorators can be an elegant and powerful tool in the hands of experienced developers.  Decorators give you the ability to modify the behavior of functions without altering their source code, providing ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/python-decorators-explained/</link>
                <guid isPermaLink="false">66d460c99208fb118cc6d006</guid>
                
                    <category>
                        <![CDATA[ beginner ]]>
                    </category>
                
                    <category>
                        <![CDATA[ decorator ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 06 Jun 2023 18:50:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/06/python_decorators_explained.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Roy Chng</p>
<p>In the world of Python programming, decorators can be an elegant and powerful tool in the hands of experienced developers. </p>
<p>Decorators give you the ability to modify the behavior of functions without altering their source code, providing a concise and flexible way to enhance and extend their functionality.</p>
<p>In this article, I'll go over the intricacies of how to use decorators in Python, and show examples of where they are useful.</p>
<h2 id="heading-quick-function-recap">Quick Function Recap</h2>
<p>Simply put, a function is a way of running a block of code repeatedly with different arguments. </p>
<p>In other words, it can take inputs, use those inputs to run some pre-defined set of code, and then return an output.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/functions.png" alt="Image" width="600" height="400" loading="lazy">
<em>Functions take in inputs, use it to run a set of code and returns an output</em></p>
<p>In Python, a function is written like so:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_one</span>(<span class="hljs-params">num</span>):</span>
    <span class="hljs-keyword">return</span> num + <span class="hljs-number">1</span>
</code></pre>
<p>When we want to call it, we can write the function's names with parenthesis and pass in the necessary inputs (arguments):</p>
<pre><code class="lang-python">final_value = add_one(<span class="hljs-number">1</span>)
print(final_value) <span class="hljs-comment"># 2</span>
</code></pre>
<p>Note that for the most part, arguments and parameters mean the same thing. They are the variables used in the function. </p>
<p>The difference lies in where we are referring to them. Arguments are what we pass into the function when calling it, and parameters are what is declared in the function.</p>
<h2 id="heading-how-to-pass-functions-as-arguments">How to Pass Functions as Arguments</h2>
<p>Commonly, when calling functions with arguments, we pass values such as Integers, Floats, Strings, Lists, Dictionaries and other data types.</p>
<p>But, something we can also do is to pass a function as an argument as well:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inner_function</span>():</span>
    print(<span class="hljs-string">"inner_function is called"</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">outer_function</span>(<span class="hljs-params">func</span>):</span>
    print(<span class="hljs-string">"outer_function is called"</span>)
     func()

outer_function(inner_function)
<span class="hljs-comment"># outer_function is called</span>
<span class="hljs-comment"># inner_function is called</span>
</code></pre>
<p>In this example we create two functions: <code>inner_function</code> and <code>outer_function</code>.</p>
<p> <code>outer_function</code> has a parameter called <code>func</code> which it calls after it itself is called.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/first_class_citizens.png" alt="Image" width="600" height="400" loading="lazy">
_outer<em>function executes first. It then calls the function that was passed as a parameter</em></p>
<p>Think about it like how we can treat functions like any other value or variable. </p>
<p>The proper term for this is that functions are <strong>first class citizens</strong>. This means that they are just like any other object and can be passed as arguments into other functions, be assigned to variables, or returned by other functions.</p>
<p>So, <code>outer_function</code> can take in a function as a parameter and call it when it is executed.</p>
<h2 id="heading-how-to-return-functions">How to Return Functions</h2>
<p>Another benefit of being able to treat functions as objects is that we can define them in other functions and return them as well:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">outer_function</span>():</span>
    print(<span class="hljs-string">"outer_function is called"</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inner_function</span>():</span>
            print(<span class="hljs-string">"inner_function is called"</span>)

    <span class="hljs-keyword">return</span> inner_function
</code></pre>
<p>Note that in this example, when we return <code>inner_function</code>, we didn't call it. </p>
<p>We only returned the reference to it, so that we can store and call it later on:</p>
<pre><code class="lang-python">returned_function = outer_function()
<span class="hljs-comment"># outer_funciton is called</span>

returned_function()
<span class="hljs-comment"># inner_function is called</span>
</code></pre>
<p>If you are like I am, this might seem interesting and all, but you are still probably wondering how this can be useful in actual programs 🤔.  This is something we'll take a look at in a moment!</p>
<h2 id="heading-how-to-create-decorators-in-python">How to Create Decorators in Python</h2>
<p>Accepting functions as arguments, defining functions within other functions, and returning them are exactly what we need to know to create decorators in Python. We use decorators to add additional functionality to existing functions.</p>
<p>For example, if we wanted to create a decorator that will add 1 to the return value of any function, we can do it like so:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_one_decorator</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_one</span>():</span>
        value = func()
        <span class="hljs-keyword">return</span> value + <span class="hljs-number">1</span>

    <span class="hljs-keyword">return</span> add_one
</code></pre>
<p>Now, if we have a function that returns a number, we can use this decorator to add 1 to whatever value it outputs.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">example_function</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>

final_value = add_one_decorator(example_function)
print(final_value()) <span class="hljs-comment"># 2</span>
</code></pre>
<p>In this example, we call the <code>add_one_decorator</code> function and pass in the reference to <code>example_function</code>. </p>
<p>When we call the <code>add_one_decorator</code> function, it creates a new function, <code>add_one</code>, defined within it and returns a reference to this new function. We store this function in the variable <code>final_value</code>.</p>
<p>So, when executing the <code>final_value</code> function, the <code>add_one</code> function is called.</p>
<p>The <code>add_one</code> function defined within <code>add_one_decorator</code> will then call <code>example_function</code>, store its value, and add one to it.</p>
<p>Ultimately, this results in <code>2</code> being returned and printed to the console.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/python_decorators-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Process of how the code will execute</em></p>
<p>Notice how we didn't have to change the original <code>example_function</code> to modify its return value and to add functionality to it. This is what makes decorators so useful!</p>
<p>Just to clarify, decorators aren't specific to Python. They're a concept that can be applied in other programming languages. But in Python, you can make use of them easily using the <code>@</code> syntax.</p>
<h2 id="heading-how-to-use-the-syntax-in-python">How to Use the <code>@</code> Syntax in Python</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/at_syntax.png" alt="Image" width="600" height="400" loading="lazy">
<em>The @ character</em></p>
<p>As we saw above, when we want to use decorators, we have to call the decorator function and pass in the function we want to modify.</p>
<p>In Python, we can make use of the <code>@</code> syntax to be much more efficient.</p>
<pre><code class="lang-python"><span class="hljs-meta">@add_one_decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">example_function</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>
</code></pre>
<p>By writing <code>@add_one_decorator</code> above our function, it is equivalent to the following:</p>
<pre><code class="lang-python">example_function = add_one_decorator(example_function)
</code></pre>
<p>This means that whenever we call the <code>example_function</code>, we will essentially be calling the <code>add_one</code> function defined within the decorator.</p>
<h2 id="heading-how-to-pass-arguments-with-decorators">How to Pass Arguments With Decorators</h2>
<p>When using decorators, we might also want the decorated function to be able to receive arguments when it is called from the wrapper function.</p>
<p>For example, if we had a function that requires two parameters and returns their sum:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">a,b</span>):</span>
    <span class="hljs-keyword">return</span> a + b

print(add(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>)) <span class="hljs-comment"># 3</span>
</code></pre>
<p>And if we used a decorator that added 1 to the output:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_one_decorator</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_one</span>():</span>
        value = func()
        <span class="hljs-keyword">return</span> value + <span class="hljs-number">1</span>

    <span class="hljs-keyword">return</span> add_one

<span class="hljs-meta">@add_one_decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">a,b</span>):</span>
    <span class="hljs-keyword">return</span> a + b

add(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>)
<span class="hljs-comment"># TypeError: add_one_decorator.&lt;locals&gt;.add_one() takes 0 positional arguments but 2 were given</span>
</code></pre>
<p>When doing so, we run into an error: the wrapper function (<code>add_one</code>) doesn't take any arguments but we provided two arguments. </p>
<p>To fix this, we need to pass down any arguments received from <code>add_one</code> to the decorated function when calling it:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_one_decorator</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_one</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        value = func(*args, **kwargs)
        <span class="hljs-keyword">return</span> value + <span class="hljs-number">1</span>

     <span class="hljs-keyword">return</span> add_one

<span class="hljs-meta"> @add_one_decorator</span>
 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">a,b</span>):</span>
     <span class="hljs-keyword">return</span> a+b

 print(add(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>)) <span class="hljs-comment"># 4</span>
</code></pre>
<p>We make use of <code>*args</code> and <code>**kwargs</code> to indicate that the <code>add_one</code> wrapper function should be able to receive any amount of positional arguments (<code>args</code>) and keyword arguments (<code>kwargs</code>). </p>
<p><code>args</code> will be a list of all the positional keywords given, in this case <code>[1,2].</code></p>
<p><code>kwargs</code> will be a dictionary with keys as the keywords arguments used and the values as the values assigned to them, in this case an empty dictionary.</p>
<p>Writing <code>func(*args, **kwargs)</code> indicates that we want to call <code>func</code> with the same positional and keyword arguments that was received</p>
<p>This ensures that all the positional and keyword arguments passed into the decorated function will be passed into the original function.</p>
<h2 id="heading-why-are-decorators-in-python-useful-real-code-examples">Why Are Decorators In Python Useful? Real Code Examples</h2>
<p>Now that we've taken a look at what exactly are Python decorators, let's see some real-world examples of when decorates are useful.</p>
<h3 id="heading-logging">Logging</h3>
<p>When building larger applications, it is often helpful to have logs of what functions were executed with information, such as what arguments were used, and what the function returned during the application's runtime.</p>
<p>This can be incredibly useful for troubleshooting and debugging when things go wrong, to help pinpoint where the problem originiated from. Even if not for debugging, logging can be useful for monitoring the status of your program.</p>
<p>Here's a simple example of how we can create a simple logger (using the built-in Python <code>logging</code> package) to save information about our application as it is running, into a file named <code>main.log</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">function_logger</span>(<span class="hljs-params">func</span>):</span>
    logging.basicConfig(level = logging.INFO, filename=<span class="hljs-string">"main.log"</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        result = func(*args, **kwargs)
        logging.info(<span class="hljs-string">f"<span class="hljs-subst">{func.__name__}</span> ran with positional arguments: <span class="hljs-subst">{args}</span> and keyword arguments: <span class="hljs-subst">{kwargs}</span>. Return value: <span class="hljs-subst">{result}</span>"</span>)
        <span class="hljs-keyword">return</span> result

    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@function_logger</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_one</span>(<span class="hljs-params">value</span>):</span>
    <span class="hljs-keyword">return</span> value + <span class="hljs-number">1</span>

print(add_one(<span class="hljs-number">1</span>))
</code></pre>
<p>Whenever the <code>add_one</code> function runs, a new log will be appended to the <code>main.log</code> file:</p>
<pre><code>INFO:root:add_one ran <span class="hljs-keyword">with</span> positional <span class="hljs-built_in">arguments</span>: (<span class="hljs-number">1</span>,) and keyword <span class="hljs-built_in">arguments</span>: {}. Return value: <span class="hljs-number">2</span>
</code></pre><h3 id="heading-caching">Caching</h3>
<p>If we have an application that requires running the same function multiple times with the same arguments, returning the same value, it can quickly become inefficient and take up unnecessary resources.</p>
<p>To prevent this, it can be useful to store the arguments used and the returned value of the function any time it is called, and simply re-use the returned value if we have already called the function with the same arguments.</p>
<p>In Python, this can be implemented by using the <code>@lru_cache</code> decorator from the <code>functools</code> module which comes installed with Python.</p>
<p><strong>LRU</strong> refers to <strong>Least Recently Used</strong>, meaning that whenever the function has been called, the arguments used and returned value will be stored. But once the number of such entries has reached the maximum size, which by default is 128, the least recently used entry will be removed.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> lru_cache

<span class="hljs-meta">@lru_cache</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fibonacci</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-keyword">if</span> n &lt;= <span class="hljs-number">1</span>:
        <span class="hljs-keyword">return</span> n
    <span class="hljs-keyword">return</span> fibonacci(n - <span class="hljs-number">1</span>) + fibonacci(n - <span class="hljs-number">2</span>)
</code></pre>
<p>In this example, the function <code>fibonacci</code> takes in the argument <code>n</code> and if it is less than <code>1</code>, returns <code>n</code>, otherwise returning the sum of the function called with <code>n-1</code> and <code>n-2</code>.</p>
<p>So, if the function is called with <code>n=10</code>, it returns <code>55</code>:</p>
<pre><code class="lang-python">print(fibnoacci(<span class="hljs-number">10</span>))
<span class="hljs-comment"># 55</span>
</code></pre>
<p>In this case, when we call the function <code>fibonacci(10)</code>, it calls the function <code>fibonacci(9)</code> and <code>fibonacci(8)</code>, and so on, until it reaches 1 or 0.</p>
<p>If we were to then use this function more than once:</p>
<pre><code class="lang-python">fibonacci(<span class="hljs-number">50</span>)
fibonacci(<span class="hljs-number">100</span>)
</code></pre>
<p>We can make use of the cache of the entries that have been saved. So when we call <code>fibonacci(50)</code>, it can stop calling the <code>fibonacci</code> function once it reaches <code>10</code> and when we call <code>fibonacci(100)</code>, it can stop calling the function once it reaches <code>50</code>, making the program far more efficient.</p>
<p>These examples have one thing in common, which is that they are incredibly easy to implement to your pre-existing functions in Python. You do not need to alter your code or manually wrap your function in another. </p>
<p>Being able to simply use the <code>@</code> syntax makes it a breeze to leverage additional modules and packages.</p>
<h2 id="heading-summary">Summary</h2>
<p>Python decorators make it possible to effortlessly extend functions without having to modify them. In this tutorial, you learned how decorators work and saw some examples of where they can be used.</p>
<p>If you enjoy my writing, consider checking out my <a target="_blank" href="https://www.youtube.com/@turbinethree">YouTube channel</a> for more Python content.</p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Python Decorators – How to Create and Use Decorators in Python With Examples ]]>
                </title>
                <description>
                    <![CDATA[ By Brandon Wallace Python decorators allow you to change the behavior of a function without modifying the function itself. In this article I will show you how to create and use decorators. You will see how easy it is to use this advanced Python featu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/python-decorators-explained-with-examples/</link>
                <guid isPermaLink="false">66d84e53c15439a8d5631e4d</guid>
                
                    <category>
                        <![CDATA[ decorator ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 15 Jun 2021 17:57:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/06/cover_image9.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Brandon Wallace</p>
<p>Python decorators allow you to change the behavior of a function without modifying the function itself.</p>
<p>In this article I will show you how to create and use decorators. You will see how easy it is to use this advanced Python feature.</p>
<p>In this article I will discuss the following topics:</p>
<ul>
<li>When to use a decorator in Python</li>
<li>Building blocks you use to create a decorator</li>
<li>How to create a Python decorator</li>
<li>Real-world examples of Python decorators</li>
<li>Class decorators in Python</li>
</ul>
<h2 id="heading-when-to-use-a-decorator-in-python">When to Use a Decorator in Python</h2>
<p>You'll use a decorator when you need to change the behavior of a function without modifying the function itself. A few good examples are when you want to add logging, test performance, perform caching, verify permissions, and so on.</p>
<p>You can also use one when you need to run the same code on multiple functions. This avoids you writing duplicating code.</p>
<h2 id="heading-here-are-the-building-blocks-used-to-create-python-decorators">Here are the building blocks used to create Python decorators</h2>
<p>To get a better understanding of how decorators work, you should understand a few concepts first.</p>
<ol>
<li>A function is an object. Because of that, a function can be assigned to a variable. The function can be accessed from that variable.</li>
</ol>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_function</span>():</span>

    print(<span class="hljs-string">'I am a function.'</span>)

<span class="hljs-comment"># Assign the function to a variable without parenthesis. We don't want to execute the function.</span>

description = my_function
</code></pre>
<pre><code class="lang-python"><span class="hljs-comment"># Accessing the function from the variable I assigned it to.</span>

print(description())

<span class="hljs-comment"># Output</span>

<span class="hljs-string">'I am a function.'</span>
</code></pre>
<ol start="2">
<li>A function can be nested within another function.</li>
</ol>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">outer_function</span>():</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inner_function</span>():</span>

        print(<span class="hljs-string">'I came from the inner function.'</span>)

    <span class="hljs-comment"># Executing the inner function inside the outer function.</span>
    inner_function()
</code></pre>
<pre><code class="lang-python">outer_function()

<span class="hljs-comment"># Output</span>

I came <span class="hljs-keyword">from</span> the inner function.
</code></pre>
<p>Note that the <code>inner_function</code> is not available outside the <code>outer_function</code>. If I try to execute the <code>inner_function</code> outside of the <code>outer_function</code> I receive a NameError exception.</p>
<pre><code class="lang-python">inner_function()

Traceback (most recent call last):
  File <span class="hljs-string">"/tmp/my_script.py"</span>, line <span class="hljs-number">9</span>, <span class="hljs-keyword">in</span> &lt;module&gt;
    inner_function()
NameError: name <span class="hljs-string">'inner_function'</span> <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> defined
</code></pre>
<ol start="3">
<li>Since a function can be nested inside another function it can also be returned.</li>
</ol>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">outer_function</span>():</span>
    <span class="hljs-string">'''Assign task to student'''</span>

    task = <span class="hljs-string">'Read Python book chapter 3.'</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inner_function</span>():</span>
        print(task)
    <span class="hljs-keyword">return</span> inner_function

homework = outer_function()
</code></pre>
<pre><code class="lang-python">homework()

<span class="hljs-comment"># Output</span>

<span class="hljs-string">'Read Python book chapter 5.'</span>
</code></pre>
<ol start="4">
<li>A function can be passed to another function as an argument.</li>
</ol>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">friendly_reminder</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-string">'''Reminder for husband'''</span>

    func()
    print(<span class="hljs-string">'Don\'t forget to bring your wallet!'</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">action</span>():</span>

    print(<span class="hljs-string">'I am going to the store buy you something nice.'</span>)
</code></pre>
<pre><code class="lang-python"><span class="hljs-comment"># Calling the friendly_reminder function with the action function used as an argument.</span>

friendly_reminder(action)

<span class="hljs-comment"># Output</span>

I am going to the store buy you something nice.
Don<span class="hljs-string">'t forget to bring your wallet!</span>
</code></pre>
<h2 id="heading-how-to-create-a-python-decorator">How to Create a Python Decorator</h2>
<p>To create a decorator function in Python, I create an outer function that takes a function as an argument. There is also an inner function that wraps around the decorated function.</p>
<p>Here is the syntax for a basic Python decorator:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_decorator_func</span>(<span class="hljs-params">func</span>):</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper_func</span>():</span>
        <span class="hljs-comment"># Do something before the function.</span>
        func()
        <span class="hljs-comment"># Do something after the function.</span>
    <span class="hljs-keyword">return</span> wrapper_func
</code></pre>
<p>To use a decorator ,you attach it to a function like you see in the code below. We use a decorator by placing the name of the decorator directly above the function we want to use it on. You prefix the decorator function with an <code>@</code> symbol.</p>
<pre><code class="lang-python"><span class="hljs-meta">@my_decorator_func</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_func</span>():</span>

    <span class="hljs-keyword">pass</span>
</code></pre>
<p>Here is a simple example. This decorator logs the date and time a function is executed:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">log_datetime</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-string">'''Log the date and time of a function'''</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>():</span>
        print(<span class="hljs-string">f'Function: <span class="hljs-subst">{func.__name__}</span>\nRun on: <span class="hljs-subst">{datetime.today().strftime(<span class="hljs-string">"%Y-%m-%d %H:%M:%S"</span>)}</span>'</span>)
        print(<span class="hljs-string">f'<span class="hljs-subst">{<span class="hljs-string">"-"</span>*<span class="hljs-number">30</span>}</span>'</span>)
        func()
    <span class="hljs-keyword">return</span> wrapper


<span class="hljs-meta">@log_datetime</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">daily_backup</span>():</span>

    print(<span class="hljs-string">'Daily backup job has finished.'</span>)   


daily_backup()

<span class="hljs-comment"># Output</span>

Daily backup job has finished.
Function: daily_backup
Run on: <span class="hljs-number">2021</span><span class="hljs-number">-06</span><span class="hljs-number">-06</span> <span class="hljs-number">06</span>:<span class="hljs-number">54</span>:<span class="hljs-number">14</span>
---------------------------
</code></pre>
<h2 id="heading-how-to-add-arguments-to-decorators-in-python">How to Add Arguments to Decorators in Python</h2>
<p>Decorators can have arguments passed to them. To add arguments to decorators I add <code>*args</code> and <code>_*_*kwargs</code> to the inner functions.</p>
<ul>
<li><code>***args**</code> will take an unlimited number of arguments of any type, such as <code>10</code>, <code>True</code>, or <code>'Brandon'</code>.</li>
<li><code>****kwargs**</code> will take an unlimited number of keyword arguments, such as <code>count=99</code>, <code>is_authenticated=True</code>, or <code>name='Brandon'</code>.</li>
</ul>
<p>Here is a decorator with arguments:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_decorator_func</span>(<span class="hljs-params">func</span>):</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper_func</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        <span class="hljs-comment"># Do something before the function.</span>
        func(*args, **kwargs)
        <span class="hljs-comment"># Do something after the function.</span>
    <span class="hljs-keyword">return</span> wrapper_func


<span class="hljs-meta">@my_decorator_func</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_func</span>(<span class="hljs-params">my_arg</span>):</span>
    <span class="hljs-string">'''Example docstring for function'''</span>

    <span class="hljs-keyword">pass</span>
</code></pre>
<p>Decorators hide the function they are decorating. If I check the <code>__name__</code> or <code>__doc__</code> method we get an unexpected result.</p>
<pre><code class="lang-python">print(my_func.__name__)
print(my_func.__doc__)

<span class="hljs-comment"># Output</span>

wrapper_func
<span class="hljs-literal">None</span>
</code></pre>
<p>To fix this issue I will use <code>functools</code>. Functools wraps will update the decorator with the decorated functions attributes.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_decorator_func</span>(<span class="hljs-params">func</span>):</span>

<span class="hljs-meta">    @wraps(func)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper_func</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        func(*args, **kwargs)
    <span class="hljs-keyword">return</span> wrapper_func

<span class="hljs-meta">@my_decorator_func</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_func</span>(<span class="hljs-params">my_args</span>):</span>
    <span class="hljs-string">'''Example docstring for function'''</span>

    <span class="hljs-keyword">pass</span>
</code></pre>
<p>Now I receive the output I am expecting.</p>
<pre><code class="lang-python">print(my_func.__name__)
print(my_func.__doc__)

<span class="hljs-comment"># Output</span>

my_func
Example docstring <span class="hljs-keyword">for</span> function
</code></pre>
<h2 id="heading-example-of-a-python-decorator-in-action">Example of a Python Decorator in Action</h2>
<p>I have created a decorator that will measure memory and speed of a function.<br>We'll use the decorator to test the performance list generation using four methods: range, list comprehension, append, and concatenation.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps
<span class="hljs-keyword">import</span> tracemalloc
<span class="hljs-keyword">from</span> time <span class="hljs-keyword">import</span> perf_counter 


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">measure_performance</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-string">'''Measure performance of a function'''</span>

<span class="hljs-meta">    @wraps(func)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        tracemalloc.start()
        start_time = perf_counter()
        func(*args, **kwargs)
        current, peak = tracemalloc.get_traced_memory()
        finish_time = perf_counter()
        print(<span class="hljs-string">f'Function: <span class="hljs-subst">{func.__name__}</span>'</span>)
        print(<span class="hljs-string">f'Method: <span class="hljs-subst">{func.__doc__}</span>'</span>)
        print(<span class="hljs-string">f'Memory usage:\t\t <span class="hljs-subst">{current / <span class="hljs-number">10</span>**<span class="hljs-number">6</span>:<span class="hljs-number">.6</span>f}</span> MB \n'</span>
              <span class="hljs-string">f'Peak memory usage:\t <span class="hljs-subst">{peak / <span class="hljs-number">10</span>**<span class="hljs-number">6</span>:<span class="hljs-number">.6</span>f}</span> MB '</span>)
        print(<span class="hljs-string">f'Time elapsed is seconds: <span class="hljs-subst">{finish_time - start_time:<span class="hljs-number">.6</span>f}</span>'</span>)
        print(<span class="hljs-string">f'<span class="hljs-subst">{<span class="hljs-string">"-"</span>*<span class="hljs-number">40</span>}</span>'</span>)
        tracemalloc.stop()
    <span class="hljs-keyword">return</span> wrapper


<span class="hljs-meta">@measure_performance</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">make_list1</span>():</span>
    <span class="hljs-string">'''Range'''</span>

    my_list = list(range(<span class="hljs-number">100000</span>))


<span class="hljs-meta">@measure_performance</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">make_list2</span>():</span>
    <span class="hljs-string">'''List comprehension'''</span>

    my_list = [l <span class="hljs-keyword">for</span> l <span class="hljs-keyword">in</span> range(<span class="hljs-number">100000</span>)]


<span class="hljs-meta">@measure_performance</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">make_list3</span>():</span>
    <span class="hljs-string">'''Append'''</span>

    my_list = []
    <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> range(<span class="hljs-number">100000</span>):
        my_list.append(item)


<span class="hljs-meta">@measure_performance</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">make_list4</span>():</span>
    <span class="hljs-string">'''Concatenation'''</span>

    my_list = []
    <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> range(<span class="hljs-number">100000</span>):
        my_list = my_list + [item]


print(make_list1())
print(make_list2())
print(make_list3())
print(make_list4())

<span class="hljs-comment"># Output</span>

Function: make_list1
Method: Range
Memory usage:                <span class="hljs-number">0.000072</span> MB 
Peak memory usage:            <span class="hljs-number">3.693040</span> MB 
Time elapsed <span class="hljs-keyword">is</span> seconds:    <span class="hljs-number">0.049359</span>
----------------------------------------

Function: make_list2
Method: List comprehension
Memory usage:                <span class="hljs-number">0.000856</span> MB 
Peak memory usage:            <span class="hljs-number">3.618244</span> MB 
Time elapsed <span class="hljs-keyword">is</span> seconds:    <span class="hljs-number">0.052338</span>
----------------------------------------

Function: make_list3
Method: Append
Memory usage:                <span class="hljs-number">0.000448</span> MB 
Peak memory usage:            <span class="hljs-number">3.617692</span> MB 
Time elapsed <span class="hljs-keyword">is</span> seconds:    <span class="hljs-number">0.060719</span>
----------------------------------------

Function: make_list4
Method: Concatenation
Memory usage:                <span class="hljs-number">0.000440</span> MB 
Peak memory usage:            <span class="hljs-number">4.393292</span> MB 
Time elapsed <span class="hljs-keyword">is</span> seconds:    <span class="hljs-number">61.649138</span>
----------------------------------------
</code></pre>
<p>You can use decorators with classes as well. Let's see how you use decorators with a Python class.</p>
<p>In this example, notice there is no <code>@</code> character involved. With the <code>__call__</code> method the decorator is executed when an instance of the class is created.</p>
<p>This class keeps track of the number of times a function to query to an API has been run. Once it reaches the limit the decorator stops the function from executing.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LimitQuery</span>:</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, func</span>):</span>
        self.func = func
        self.count = <span class="hljs-number">0</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__call__</span>(<span class="hljs-params">self, *args, **kwargs</span>):</span>
        self.limit = args[<span class="hljs-number">0</span>]
        <span class="hljs-keyword">if</span> self.count &lt; self.limit:
            self.count += <span class="hljs-number">1</span>
            <span class="hljs-keyword">return</span> self.func(*args, **kwargs)
        <span class="hljs-keyword">else</span>:
            print(<span class="hljs-string">f'No queries left. All <span class="hljs-subst">{self.count}</span> queries used.'</span>)
            <span class="hljs-keyword">return</span>

<span class="hljs-meta">@LimitQuery</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_coin_price</span>(<span class="hljs-params">limit</span>):</span>
    <span class="hljs-string">'''View the Bitcoin Price Index (BPI)'''</span>

    url = requests.get(<span class="hljs-string">'https://api.coindesk.com/v1/bpi/currentprice.json'</span>)

    <span class="hljs-keyword">if</span> url.status_code == <span class="hljs-number">200</span>:
        text = url.json()
        <span class="hljs-keyword">return</span> <span class="hljs-string">f"$<span class="hljs-subst">{float(text[<span class="hljs-string">'bpi'</span>][<span class="hljs-string">'USD'</span>][<span class="hljs-string">'rate_float'</span>]):<span class="hljs-number">.2</span>f}</span>"</span>


print(get_coin_price(<span class="hljs-number">5</span>))
print(get_coin_price(<span class="hljs-number">5</span>))
print(get_coin_price(<span class="hljs-number">5</span>))
print(get_coin_price(<span class="hljs-number">5</span>))
print(get_coin_price(<span class="hljs-number">5</span>))
print(get_coin_price(<span class="hljs-number">5</span>))

<span class="hljs-comment"># Output</span>

$<span class="hljs-number">35968.25</span>
$<span class="hljs-number">35896.55</span>
$<span class="hljs-number">34368.14</span>
$<span class="hljs-number">35962.27</span>
$<span class="hljs-number">34058.26</span>
No queries left. All <span class="hljs-number">5</span> queries used.
</code></pre>
<p>This class will keep track of the state of the class.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In this article I talked about how to pass a function to a variable, nested functions, returning functions, and passing a function to another function as an argument.</p>
<p>I also showed you how to create and use Python decorators along with a few real-world examples. Now I hope that you will able to add decorators to your projects.</p>
<p>Follow me on <a target="_blank" href="https://github.com/brandon-wallace">Github</a> | <a target="_blank" href="https://dev.to/brandonwallace">DEV.to</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The 3 Types of Design Patterns All Developers Should Know (with code examples of each) ]]>
                </title>
                <description>
                    <![CDATA[ By Sameeha Rahman What is a Design Pattern? Design patterns are design level solutions for recurring problems that we software engineers come across often. It’s not code - I repeat, ❌CODE. It is like a description on how to tackle these problems and ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-basic-design-patterns-all-developers-need-to-know/</link>
                <guid isPermaLink="false">66d460cfe39d8b5612bc0df1</guid>
                
                    <category>
                        <![CDATA[ command ]]>
                    </category>
                
                    <category>
                        <![CDATA[ decorator ]]>
                    </category>
                
                    <category>
                        <![CDATA[ design patterns ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ object oriented ]]>
                    </category>
                
                    <category>
                        <![CDATA[ singleton ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 24 Jul 2019 06:52:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/07/design-patterns-everywhere.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sameeha Rahman</p>
<h1 id="heading-what-is-a-design-pattern">What is a Design Pattern?</h1>
<p>Design patterns are design level solutions for recurring problems that we software engineers come across often. It’s not code - I repeat, ❌<strong>CODE</strong>. It is like a description on how to tackle these problems and design a solution. </p>
<p>Using these patterns is considered good practice, as the design of the solution is quite tried and tested, resulting in higher readability of the final code. Design patterns are quite often created for and used by OOP Languages, like Java, in which most of the examples from here on will be written.</p>
<h2 id="heading-types-of-design-patterns">Types of design patterns</h2>
<p>There are about 26 Patterns currently discovered (I hardly think I will do them all…).</p>
<p>These 26 can be classified into 3 types:</p>
<ol>
<li><p>Creational: These patterns are designed for class instantiation. They can be either class-creation patterns or object-creational patterns.</p>
</li>
<li><p>Structural: These patterns are designed with regard to a class's structure and composition. The main goal of most of these patterns is to increase the functionality of the class(es) involved, without changing much of its composition.</p>
</li>
<li><p>Behavioral: These patterns are designed depending on how one class communicates with others.</p>
</li>
</ol>
<p>In this post, we will go through one basic design pattern for each classified type.</p>
<h2 id="heading-type-1-creational-the-singleton-design-pattern">Type 1: Creational - The Singleton Design Pattern</h2>
<p>The Singleton Design Pattern is a Creational pattern, whose objective is to create only one instance of a class and to provide only one global access point to that object. One commonly used example of such a class in Java is Calendar, where you cannot make an instance of that class. It also uses its own <code>getInstance()</code>method to get the object to be used.</p>
<p>A class using the singleton design pattern will include,</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/singleton-class-diagram.png" alt="Image" width="600" height="400" loading="lazy">
<em>Singleton Class Diagram</em></p>
<ol>
<li>A private static variable, holding the only instance of the class.</li>
<li>A private constructor, so it cannot be instantiated anywhere else.</li>
<li>A public static method, to return the single instance of the class.</li>
</ol>
<p>There are many different implementations of singleton design. Today, I’ll be going through the implementations of;</p>
<ol>
<li><p>Eager Instantiation</p>
</li>
<li><p>Lazy Instantiation</p>
</li>
<li><p>Thread-safe Instantiation</p>
</li>
</ol>
<h3 id="heading-eager-beaver">Eager Beaver</h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EagerSingleton</span> </span>{
    <span class="hljs-comment">// create an instance of the class.</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> EagerSingleton instance = <span class="hljs-keyword">new</span> EagerSingleton();

    <span class="hljs-comment">// private constructor, so it cannot be instantiated outside this class.</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">EagerSingleton</span><span class="hljs-params">()</span> </span>{  }

    <span class="hljs-comment">// get the only instance of the object created.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> EagerSingleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> instance;
    }
}
</code></pre>
<p>This type of instantiation happens during class loading, as the instantiation of the variable instance happens outside any method. This poses a hefty drawback if this class is not being used at all by the client application. The contingency plan, if this class is not being used, is the Lazy Instantiation.</p>
<h3 id="heading-lazy-days">Lazy Days</h3>
<p>There isn’t much difference from the above implementation. The main differences are that the static variable is initially declared null, and is only instantiated within the <code>getInstance()</code> method if - and only if - the instance variable remains null at the time of the check. </p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LazySingleton</span> </span>{
    <span class="hljs-comment">// initialize the instance as null.</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> LazySingleton instance = <span class="hljs-keyword">null</span>;

    <span class="hljs-comment">// private constructor, so it cannot be instantiated outside this class.</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">LazySingleton</span><span class="hljs-params">()</span> </span>{  }

    <span class="hljs-comment">// check if the instance is null, and if so, create the object.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> LazySingleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
            instance = <span class="hljs-keyword">new</span> LazySingleton();
        }
        <span class="hljs-keyword">return</span> instance;
    }
}
</code></pre>
<p>This fixes one problem, but another one still exists. What if two different clients access the Singleton class at the same time, right to the millisecond? Well, they will check if the instance is null at the same time, and will find it true, and so will create two instances of the class for each request by the two clients. To fix this, Thread Safe instantiation is to be implemented.</p>
<h3 id="heading-thread-safety-is-key">(Thread) Safety is Key</h3>
<p>In Java, the keyword synchronized is used on methods or objects to implement thread safety, so that only one thread will access a particular resource at one time. The class instantiation is put within a synchronized block so that the method can only be accessed by one client at a given time.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ThreadSafeSingleton</span> </span>{
    <span class="hljs-comment">// initialize the instance as null.</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> ThreadSafeSingleton instance = <span class="hljs-keyword">null</span>;

    <span class="hljs-comment">// private constructor, so it cannot be instantiated outside this class.</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">ThreadSafeSingleton</span><span class="hljs-params">()</span> </span>{  }

    <span class="hljs-comment">// check if the instance is null, within a synchronized block. If so, create the object</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> ThreadSafeSingleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (ThreadSafeSingleton.class) {
            <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
                instance = <span class="hljs-keyword">new</span> ThreadSafeSingleton();
            }
        }
        <span class="hljs-keyword">return</span> instance;
    }
}
</code></pre>
<p>The overhead for the synchronized method is high, and reduces the performance of the whole operation. </p>
<p>For example, if the instance variable has already been instantiated, then each time any client accesses the <code>getInstance()</code> method, the <code>synchronized</code> method is run and the performance drops. This just happens in order to check if the <code>instance</code> variables’ value is null. If it finds that it is, it leaves the method. </p>
<p>To reduce this overhead, double locking is used. The check is used before the <code>synchronized</code> method as well, and if the value is null alone, does the <code>synchronized</code> method run.</p>
<pre><code class="lang-java"><span class="hljs-comment">// double locking is used to reduce the overhead of the synchronized method</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> ThreadSafeSingleton <span class="hljs-title">getInstanceDoubleLocking</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
        <span class="hljs-keyword">synchronized</span> (ThreadSafeSingleton.class) {
            <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
                instance = <span class="hljs-keyword">new</span> ThreadSafeSingleton();
            }
        }
    }
    <span class="hljs-keyword">return</span> instance;
}
</code></pre>
<p>Now onto the next classification.</p>
<h2 id="heading-type-2-structural-the-decorator-design-pattern">Type 2: Structural - The Decorator Design Pattern</h2>
<p>I’m gonna give you a small scenario to give a better context to why and where you should use the Decorator Pattern.</p>
<p>Say you own a coffee shop, and like any newbie, you start out with just two types of plain coffee, the house blend and dark roast. In your billing system, there was one class for the different coffee blends, which inherits the beverage abstract class. People actually start to come by and have your wonderful (albeit bitter?) coffee. Then there are the coffee newbs that, God forbid, want sugar or milk. Such a travesty for coffee!! ??</p>
<p>Now you need to have those two add-ons as well, both to the menu and unfortunately on the billing system. Originally, your IT person will make a subclass for both coffees, one including sugar, the other milk. Then, since customers are always right, one says these dreaded words:</p>
<p><em>“Can I get a milk coffee, with sugar, please?”</em></p>
<h3 id="heading-pz8">???</h3>
<p>There goes your billing system laughing in your face again. Well, back to the drawing board….</p>
<p>The IT person then adds milk coffee with sugar as another subclass to each parent coffee class. The rest of the month is smooth sailing, people lining up to have your coffee, you actually making money. ??</p>
<p>But wait, there’s more!</p>
<p>The world is against you once again. A competitor opens up across the street, with not just 4 types of coffee, but more than 10 add-ons as well!</p>
<p>You buy all those and more, to sell better coffee yourself, and just then remember that you forgot to update that dratted billing system. You quite possibly cannot make the infinite number of subclasses for any and all combinations of all the add-ons, with the new coffee blends too. Not to mention, the size of the final system.</p>
<p>Time to actually invest in a proper billing system. You find new IT personnel, who actually knows what they are doing and they say,</p>
<p><em>“Why, this will be so much easier and smaller if it used the decorator pattern.”</em></p>
<h3 id="heading-what-on-earth-is-that">What on earth is that?</h3>
<p>The decorator design pattern falls into the structural category, that deals with the actual structure of a class, whether is by inheritance, composition or both. The goal of this design is to modify an objects’ functionality at runtime. This is one of the many other design patterns that utilize abstract classes and interfaces with composition to get its desired result.</p>
<p>Let’s give Math a chance (shudder?) to bring this all into perspective.</p>
<p>Take 4 coffee blends and 10 add-ons. If we stuck to the generation of subclasses for each different combination of all the add-ons for one type of coffee. That’s:</p>
<p>(10–1)² = 9² = 81 subclasses</p>
<p>We subtract 1 from the 10, as you cannot combine one add-on with another of the same type, sugar with sugar sounds stupid. And that’s for just one coffee blend. Multiply that <strong>81 by 4</strong> and you get a whopping <strong>324</strong> different subclasses! Talk about all that coding…</p>
<p>But with the decorator pattern it will require only 16 classes in this scenario. Wanna bet?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/decorator-class-diagram.png" alt="Image" width="600" height="400" loading="lazy">
<em>Decorator Design Pattern Class diagram</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/decorator-coffee-class-diagram.png" alt="Image" width="600" height="400" loading="lazy">
<em>Class diagram according to coffee shop scenario</em></p>
<p>If we map out our scenario according to the class diagram above, we get 4 classes for the 4 coffee blends, 10 for each add-on and 1 for the abstract component and 1 more for the abstract decorator. See! 16! Now hand over that $100.?? (jk, but it will not be refused if given… just saying)</p>
<p>As you can see from above, just as the concrete coffee blends are subclasses of the beverage abstract class, the AddOn abstract class also inherits its methods from it. The add-ons, that are its subclasses, in turn inherit any new methods to add functionality to the base object when needed.</p>
<p>Let’s get to coding, to see this pattern in use.</p>
<p>First to make the Abstract beverage class, that all the different coffee blends will inherit from:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Beverage</span> </span>{
    <span class="hljs-keyword">private</span> String description;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Beverage</span><span class="hljs-params">(String description)</span> </span>{
        <span class="hljs-keyword">super</span>();
        <span class="hljs-keyword">this</span>.description = description;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getDescription</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> description;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">double</span> <span class="hljs-title">cost</span><span class="hljs-params">()</span></span>;
}
</code></pre>
<p>Then to add both the concrete coffee blend classes.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HouseBlend</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Beverage</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">HouseBlend</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">super</span>(“House blend”);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">cost</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">250</span>;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DarkRoast</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Beverage</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">DarkRoast</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">super</span>(“Dark roast”);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">cost</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">300</span>;
    }
}
</code></pre>
<p>The AddOn abstract class also inherits from the Beverage abstract class (more on this below).</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AddOn</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Beverage</span> </span>{
    <span class="hljs-keyword">protected</span> Beverage beverage;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AddOn</span><span class="hljs-params">(String description, Beverage bev)</span> </span>{
        <span class="hljs-keyword">super</span>(description);
        <span class="hljs-keyword">this</span>.beverage = bev;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> String <span class="hljs-title">getDescription</span><span class="hljs-params">()</span></span>;
}
</code></pre>
<p>And now the concrete implementations of this abstract class:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Sugar</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AddOn</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Sugar</span><span class="hljs-params">(Beverage bev)</span> </span>{
        <span class="hljs-keyword">super</span>(“Sugar”, bev);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getDescription</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> beverage.getDescription() + “ with Mocha”;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">cost</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> beverage.cost() + <span class="hljs-number">50</span>;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Milk</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AddOn</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Milk</span><span class="hljs-params">(Beverage bev)</span> </span>{
        <span class="hljs-keyword">super</span>(“Milk”, bev);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getDescription</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> beverage.getDescription() + “ with Milk”;
    }

    <span class="hljs-meta">@Override</span>  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">cost</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> beverage.cost() + <span class="hljs-number">100</span>;
    }
}
</code></pre>
<p>As you can see above, we can pass any subclass of Beverage to any subclass of AddOn, and get the added cost as well as the updated description. And, since the AddOn class is essentially of type Beverage, we can pass an AddOn into another AddOn. This way, we can add any number of add-ons to a specific coffee blend.</p>
<p>Now to write some code to test this out.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CoffeeShop</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        HouseBlend houseblend = <span class="hljs-keyword">new</span> HouseBlend();
        System.out.println(houseblend.getDescription() + “: “ + houseblend.cost());

        Milk milkAddOn = <span class="hljs-keyword">new</span> Milk(houseblend);
        System.out.println(milkAddOn.getDescription() + “: “ + milkAddOn.cost());

        Sugar sugarAddOn = <span class="hljs-keyword">new</span> Sugar(milkAddOn);
        System.out.println(sugarAddOn.getDescription() + “: “ + sugarAddOn.cost());
    }
}
</code></pre>
<p>The final result is:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/decorator-final.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>P.S. this is in Sri Lankan Rupees</em></p>
<p>It works! We were able to add more than one add-on to a coffee blend and successfully update its final cost and description, without the need to make infinite subclasses for each add-on combination for all coffee blends.</p>
<p>Finally, to the last category.</p>
<h2 id="heading-type-3-behavioral-the-command-design-pattern">Type 3: Behavioral - The Command Design Pattern</h2>
<p>A behavioral design pattern focuses on how classes and objects communicate with each other. The main focus of the command pattern is to inculcate a higher degree of loose coupling between involved parties (read: classes).</p>
<p><em>Uhhhh… What’s that?</em></p>
<p>Coupling is the way that two (or more) classes that interact with each other, well, interact. The ideal scenario when these classes interact is that they do not depend heavily on each other. That’s loose coupling. So, a better definition for loose coupling would be, classes that are interconnected, making the least use of each other.</p>
<p>The need for this pattern arose when requests needed to be sent without consciously knowing what you are asking for or who the receiver is.</p>
<p>In this pattern, the invoking class is decoupled from the class that actually performs an action. The invoker class only has the callable method execute, which runs the necessary command, when the client requests it.</p>
<p>Let’s take a basic real-world example, ordering a meal at a fancy restaurant. As the flow goes, you give your order (command) to the waiter (invoker), who then hands it over to the chef(receiver), so you can get food. Might sound simple… but a bit meh to code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/chain-of-command-be-like-pop-snoke-im-going-to-27790631.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The idea is pretty simple, but the coding goes around the nose.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/command-class-diagram.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Command Design Pattern Class Diagram</em></p>
<p>The flow of operation on the technical side is, you make a concrete command, which implements the Command interface, asking the receiver to complete an action, and send the command to the invoker. The invoker is the person that knows when to give this command. The chef is the only one who knows what to do when given the specific command/order. So, when the execute method of the invoker is run, it, in turn, causes the command objects’ execute method to run on the receiver, thus completing necessary actions.</p>
<h3 id="heading-what-we-need-to-implement-is">What we need to implement is;</h3>
<ol>
<li>An interface Command</li>
<li>A class Order that implements Command interface</li>
<li>A class Waiter (invoker)</li>
<li>A class Chef (receiver)</li>
</ol>
<p>So, the coding goes like this:</p>
<h3 id="heading-chef-the-receiver">Chef, the receiver</h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Chef</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">cookPasta</span><span class="hljs-params">()</span> </span>{
        System.out.println(“Chef is cooking Chicken Alfredo…”);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">bakeCake</span><span class="hljs-params">()</span> </span>{
        System.out.println(“Chef is baking Chocolate Fudge Cake…”);
    }
}
</code></pre>
<h3 id="heading-command-the-interface">Command, the interface</h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Command</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span></span>;
}
</code></pre>
<h3 id="heading-order-the-concrete-command">Order, the concrete command</h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Order</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Command</span> </span>{
    <span class="hljs-keyword">private</span> Chef chef;
    <span class="hljs-keyword">private</span> String food;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Order</span><span class="hljs-params">(Chef chef, String food)</span> </span>{
        <span class="hljs-keyword">this</span>.chef = chef;
        <span class="hljs-keyword">this</span>.food = food;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.food.equals(“Pasta”)) {
            <span class="hljs-keyword">this</span>.chef.cookPasta();
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">this</span>.chef.bakeCake();
        }
    }
}
</code></pre>
<h3 id="heading-waiter-the-invoker">Waiter, the invoker</h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Waiter</span> </span>{
    <span class="hljs-keyword">private</span> Order order;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Waiter</span><span class="hljs-params">(Order ord)</span> </span>{
        <span class="hljs-keyword">this</span>.order = ord;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">this</span>.order.execute();
    }
}
</code></pre>
<h2 id="heading-you-the-client">You, the client</h2>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Chef chef = <span class="hljs-keyword">new</span> Chef();

        Order order = <span class="hljs-keyword">new</span> Order(chef, “Pasta”);
        Waiter waiter = <span class="hljs-keyword">new</span> Waiter(order);
        waiter.execute();

        order = <span class="hljs-keyword">new</span> Order(chef, “Cake”);
        waiter = <span class="hljs-keyword">new</span> Waiter(order);
        waiter.execute();
    }
}
</code></pre>
<p>As you can see above, the Client makes an Order and sets the Receiver as the Chef. The Order is sent to the Waiter, who will know when to execute the Order (i.e. when to give the chef the order to cook). When the invoker is executed, the Orders’ execute method is run on the receiver (i.e. the chef is given the command to either cook pasta ? or bake cake?).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*gwsVqEIKFmBj01M7dXsQ_A.png" alt="Image" width="600" height="400" loading="lazy">
<em>Final Client Output</em></p>
<h2 id="heading-quick-recap">Quick recap</h2>
<p>In this post we went through:</p>
<ol>
<li>What a design pattern really is,</li>
<li>The different types of design patterns and why they are different</li>
<li>One basic or common design pattern for each type</li>
</ol>
<p>I hope this was helpful.  </p>
<p>Find the code repo for the post, <a target="_blank" href="https://github.com/samsam-026/Design_Patterns">here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
