{"id":15651,"date":"2025-09-11T07:19:56","date_gmt":"2025-09-11T07:19:56","guid":{"rendered":"https:\/\/www.kaashivinfotech.com\/blog\/?p=15651"},"modified":"2025-09-11T07:19:56","modified_gmt":"2025-09-11T07:19:56","slug":"decorators-in-python-6-lessons","status":"publish","type":"post","link":"https:\/\/www.kaashivinfotech.com\/blog\/decorators-in-python-6-lessons\/","title":{"rendered":"Decorators in Python: 6 Lessons I Learned the Hard Way"},"content":{"rendered":"<p>I will be frank that the first time I collided with the idea of decorators in Python, I did not understand what it was all about.<\/p>\n<p>This was like <strong><a href=\"https:\/\/www.wikitechy.com\/tutorials\/python\/python-tutorial\" target=\"_blank\" rel=\"noopener\">Python<\/a><\/strong> had thrown me into some sort of magic show where functions were enclosed in other functions and I was not able to determine what was being done.<\/p>\n<p>The thing is though that after it clicked I realized that decorators in <strong><a href=\"https:\/\/www.wikitechy.com\/tutorials\/python\/python-functions-def\" target=\"_blank\" rel=\"noopener\">python<\/a><\/strong> are one of the most powerful tools that you will ever employ.<\/p>\n<p>Imagine this:<\/p>\n<p>\ud83d\udc49 You have a function.<\/p>\n<p><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_1r_\" data-state=\"closed\">\ud83d\udc49 You desire logging, authentication or timing.<\/span><\/p>\n<p>\ud83d\udc49 Instead of rewriting the whole function, you just <em data-start=\"1320\" data-end=\"1326\">wrap<\/em> it with a decorator.<\/p>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter wp-image-15653 \" src=\"https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorators.webp\" alt=\"\" width=\"597\" height=\"231\" srcset=\"https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorators.webp 1120w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorators-300x116.webp 300w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorators-1024x397.webp 1024w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorators-768x298.webp 768w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorators-380x147.webp 380w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorators-800x310.webp 800w\" sizes=\"(max-width: 597px) 100vw, 597px\" \/><\/p>\n<h2>1. What Are Decorators in Python?<\/h2>\n<p>Let\u2019s start with the basics.<\/p>\n<p>Decorators Python decorators are functions that act on another function (or even a class) and alter its behavior, without making any permanent changes.<\/p>\n<p>Think of it like this:<\/p>\n<ul data-start=\"1806\" data-end=\"1974\">\n<li data-start=\"1806\" data-end=\"1851\">\n<p data-start=\"1808\" data-end=\"1851\">You have a plain cake \ud83c\udf70 (your function).<\/p>\n<\/li>\n<li data-start=\"1852\" data-end=\"1900\">\n<p data-start=\"1854\" data-end=\"1900\">You add icing and sprinkles (the decorator).<\/p>\n<\/li>\n<li data-start=\"1901\" data-end=\"1974\">\n<p data-start=\"1903\" data-end=\"1974\">The cake is still the same inside, but it\u2019s now tastier and prettier.<\/p>\n<\/li>\n<\/ul>\n<p data-start=\"1976\" data-end=\"2062\">That\u2019s what decorators do in Python\u2014they add functionality in a clean, reusable way.<\/p>\n<p data-start=\"1976\" data-end=\"2062\"><strong>Example:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">def decorator_function(original_function):\r\n    def wrapper_function():\r\n        print(\"Before the function runs\")\r\n        original_function()\r\n        print(\"After the function runs\")\r\n    return wrapper_function\r\n\r\n@decorator_function\r\ndef say_hello():\r\n    print(\"Hello, World!\")\r\n\r\nsay_hello()\r\n<\/pre>\n<p><strong>Output:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">Before the function runs  \r\nHello, World!  \r\nAfter the function runs  \r\n<\/pre>\n<p>See what happened? <span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_27_\" data-state=\"closed\">The say_hello function was wrapped with additional functionality &#8211; without me having to alter the core of the functionality.<\/span><\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-15654 size-full\" src=\"https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Decorators-in-Python2.webp\" alt=\"\" width=\"1800\" height=\"570\" srcset=\"https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Decorators-in-Python2.webp 1800w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Decorators-in-Python2-300x95.webp 300w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Decorators-in-Python2-1024x324.webp 1024w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Decorators-in-Python2-768x243.webp 768w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Decorators-in-Python2-1536x486.webp 1536w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Decorators-in-Python2-380x120.webp 380w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Decorators-in-Python2-800x253.webp 800w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Decorators-in-Python2-1160x367.webp 1160w\" sizes=\"(max-width: 1800px) 100vw, 1800px\" \/><\/p>\n<h2><strong>2. Why Use Decorators in Python?<\/strong><\/h2>\n<p><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_2a_\" data-state=\"closed\">The first time I did a web application in Flask (a Python web framework) I observed something.<\/span> <span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_2b_\" data-state=\"closed\">We did not rewrite code per page to gain routes.<\/span> Instead, we used a decorator:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">@app.route('\/dashboard')\r\n@login_required\r\ndef dashboard():\r\n    return \"Welcome to your dashboard!\"\r\n<\/pre>\n<p>The decorator login required immediately verified the presence of a user\u2019s presence via the system-administered login process- no longer did I need to repeat the user logged in logic at every other spot.<\/p>\n<p>That\u2019s when I realized:<\/p>\n<ul>\n<li><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_1o_\" data-state=\"closed\">Less code translators in Python = less code + cleaner code.<\/span><\/li>\n<li><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_1p_\" data-state=\"closed\">And quite frankly, the smaller the code, the smaller the headaches.<\/span><\/li>\n<\/ul>\n<h2><strong>3. How Decorators in Python Actually Work<\/strong><\/h2>\n<p><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_1o_\" data-state=\"closed\">Decorators in Python are based on two things:<\/span><\/p>\n<ul>\n<li><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_1p_\" data-state=\"closed\">Functions are first-class objects (functions are movable around just like variables).<\/span><\/li>\n<li><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_1q_\" data-state=\"closed\">Functions within functions.<\/span><\/li>\n<\/ul>\n<p>Here\u2019s the simple flow:<\/p>\n<ol>\n<li><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_1r_\" data-state=\"closed\">You make a wrapper function.<\/span><\/li>\n<li><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_1s_\" data-state=\"closed\">This wrapper is sent back by the decorator.<\/span><\/li>\n<li><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_1t_\" data-state=\"closed\">The wrapper puts extra behavior in the pre- or post-call of the original function.<\/span><\/li>\n<\/ol>\n<p><strong>Example with arguments:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">def repeat(num_times):\r\n    def decorator_repeat(func):\r\n        def wrapper(*args, **kwargs):\r\n            for _ in range(num_times):\r\n                func(*args, **kwargs)\r\n        return wrapper\r\n    return decorator_repeat\r\n\r\n@repeat(num_times=3)\r\ndef greet(name):\r\n    print(f\"Hello {name}!\")\r\n\r\ngreet(\"Python\")\r\n<\/pre>\n<p><strong>Output:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"nginx\">Hello Python!  \r\nHello Python!  \r\nHello Python!  \r\n<\/pre>\n<h2 data-start=\"4110\" data-end=\"4151\"><img decoding=\"async\" class=\"aligncenter wp-image-15655 \" src=\"https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorator5.webp\" alt=\"\" width=\"691\" height=\"288\" srcset=\"https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorator5.webp 2500w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorator5-300x125.webp 300w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorator5-1024x427.webp 1024w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorator5-768x320.webp 768w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorator5-1536x640.webp 1536w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorator5-2048x854.webp 2048w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorator5-380x158.webp 380w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorator5-800x333.webp 800w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/python-decorator5-1160x483.webp 1160w\" sizes=\"(max-width: 691px) 100vw, 691px\" \/><\/h2>\n<h2 data-start=\"4110\" data-end=\"4151\"><strong>4. Types of Decorators in Python\u00a0<\/strong><\/h2>\n<p data-start=\"4153\" data-end=\"4278\">There are several ways to use <strong data-start=\"4183\" data-end=\"4207\">decorators in Python<\/strong>, and knowing them helps you decide which one to use in your project.<\/p>\n<ul data-start=\"4280\" data-end=\"4488\">\n<li data-start=\"4280\" data-end=\"4342\">\n<p data-start=\"4282\" data-end=\"4342\"><strong data-start=\"4282\" data-end=\"4305\">Function Decorators<\/strong> \u2013 the most common ones you\u2019ll see.<\/p>\n<\/li>\n<li data-start=\"4343\" data-end=\"4403\">\n<p data-start=\"4345\" data-end=\"4403\"><strong data-start=\"4345\" data-end=\"4365\">Class Decorators<\/strong> \u2013 yes, you can wrap entire classes!<\/p>\n<\/li>\n<li data-start=\"4404\" data-end=\"4488\">\n<p data-start=\"4406\" data-end=\"4488\"><strong data-start=\"4406\" data-end=\"4429\">Built-in Decorators<\/strong> \u2013 like <code class=\"\" data-line=\"\">@staticmethod<\/code>, <code class=\"\" data-line=\"\">@classmethod<\/code>, and <code class=\"\" data-line=\"\">@property<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p><strong>Example of built-in decorator:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">class Person:\r\n    def __init__(self, name):\r\n        self._name = name\r\n\r\n    @property\r\n    def name(self):\r\n        return self._name\r\n\r\np = Person(\"Alice\")\r\nprint(p.name)\r\n<\/pre>\n<p>Here, <code class=\"\" data-line=\"\">@property<\/code> makes the method behave like an attribute.<\/p>\n<h2>5. Real-Life Uses of Decorators in Python<\/h2>\n<p><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_21_\" data-state=\"closed\">I use the decorators in Python everywhere.<\/span> Here are some practical uses:<\/p>\n<p><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_22_\" data-state=\"closed\"><strong>Logging<\/strong> &#8211; record the time functions are invoked.<\/span><\/p>\n<p><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_23_\" data-state=\"closed\"><strong>Authentication<\/strong> &#8211; web application secure routes (such as my Flask example).<\/span><\/p>\n<p><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_24_\" data-state=\"closed\"><strong>Performance Tracking<\/strong> &#8211; time a function is taken to execute.<\/span><\/p>\n<p><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_25_\" data-state=\"closed\"><strong>Validation of inputs<\/strong> &#8211; verify inputs before the function is executed.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">import time\r\n\r\ndef timer(func):\r\n    def wrapper(*args, **kwargs):\r\n        start = time.time()\r\n        result = func(*args, **kwargs)\r\n        end = time.time()\r\n        print(f\"{func.__name__} ran in {end - start:.4f} seconds\")\r\n        return result\r\n    return wrapper\r\n\r\n@timer\r\ndef process_data():\r\n    time.sleep(2)\r\n    print(\"Data processed\")\r\n\r\nprocess_data()\r\n<\/pre>\n<h2 data-start=\"5623\" data-end=\"5690\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15657 \" src=\"https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Types-of-Decorators-in-Python.webp\" alt=\"\" width=\"547\" height=\"308\" srcset=\"https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Types-of-Decorators-in-Python.webp 1280w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Types-of-Decorators-in-Python-300x169.webp 300w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Types-of-Decorators-in-Python-1024x576.webp 1024w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Types-of-Decorators-in-Python-768x432.webp 768w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Types-of-Decorators-in-Python-380x214.webp 380w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Types-of-Decorators-in-Python-800x450.webp 800w, https:\/\/www.kaashivinfotech.com\/blog\/wp-content\/uploads\/2025\/09\/Types-of-Decorators-in-Python-1160x653.webp 1160w\" sizes=\"(max-width: 547px) 100vw, 547px\" \/><\/h2>\n<h2 data-start=\"5623\" data-end=\"5690\"><strong>6. Common Mistakes Beginners Make with Decorators in Python<\/strong><\/h2>\n<p data-start=\"5692\" data-end=\"5740\">I\u2019ve been there too. Here are mistakes I made:<\/p>\n<ul data-start=\"5741\" data-end=\"5939\">\n<li data-start=\"5741\" data-end=\"5813\">\n<p data-start=\"5743\" data-end=\"5813\">Forgetting to return the inner function (your decorator will break).<\/p>\n<\/li>\n<li data-start=\"5814\" data-end=\"5880\">\n<p data-start=\"5816\" data-end=\"5880\">Using decorators without understanding <code class=\"\" data-line=\"\">*args<\/code> and <code class=\"\" data-line=\"\">**kwargs<\/code>.<\/p>\n<\/li>\n<li data-start=\"5881\" data-end=\"5939\">\n<p data-start=\"5883\" data-end=\"5939\">Over-decorating functions (yes, you can go overboard).<\/p>\n<\/li>\n<\/ul>\n<h2>Conclusion:<\/h2>\n<div class=\"whitespace-pre-line p-2 sm:p-1 min-h-[80px]  max-w-full overflow-x-auto\"><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_29_\" data-state=\"closed\">Python has decorators, and they are magic, provided you use them prudently.<\/span> <span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_2a_\" data-state=\"closed\">They render your code reusable, cleaner and professional.<\/span> <span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_2b_\" data-state=\"closed\">I cannot imagine doing a Python project without them anymore myself.<\/span><\/div>\n<div>Want to learn <strong><a href=\"https:\/\/www.kaashivinfotech.com\/python-course\/\">Python Course<\/a><\/strong>, <strong><a href=\"https:\/\/www.kaashivinfotech.com\/python-full-stack-development-course-in-chennai\/\">Python Fullstack Development Course<\/a><\/strong> visit our website <a href=\"https:\/\/www.kaashivinfotech.com\/\">www.kaashivinfotech.com<\/a><\/div>\n<div class=\"whitespace-pre-line p-2 sm:p-1 min-h-[80px]  max-w-full overflow-x-auto\"><span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_2c_\" data-state=\"closed\">You may be new and there is no need to worry, it took me time to learn.<\/span> <span aria-haspopup=\"dialog\" aria-expanded=\"false\" aria-controls=\"radix-_r_2d_\" data-state=\"closed\">Simply train with little decorators such as logging or timers and you will slowly realize the beauty in them.<\/span><\/div>\n<h2><strong>Related Reads:<\/strong><\/h2>\n<ul>\n<li>\n<p class=\"entry-title\"><a href=\"https:\/\/www.kaashivinfotech.com\/blog\/how-to-use-timedelta-in-python\/\">How to Use Timedelta in Python to Add and Subtract Dates (2025 Guide)<\/a><\/p>\n<\/li>\n<li>\n<p class=\"entry-title\"><a href=\"https:\/\/www.kaashivinfotech.com\/blog\/what-is-python-interpreter-guide\/\">What is Python Interpreter? Complete Beginner-Friendly Guide 2025<\/a><\/p>\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>I will be frank that the first time I collided with the idea of decorators in Python, I did not understand what it was all about. This was like Python had thrown me into some sort of magic show where functions were enclosed in other functions and I was not able to determine what was [&hellip;]<\/p>\n","protected":false},"author":8,"featured_media":15658,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3236],"tags":[9035,9033,9030,9032,9029,9034,9031,9028],"class_list":["post-15651","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python","tag-class-decorators-in-python","tag-decorators-in-python-documentation","tag-decorators-in-python-example","tag-decorators-in-python-geeksforgeeks","tag-decorators-in-python-w3schools","tag-generators-and-decorators-in-python","tag-python-decorator-with-arguments","tag-types-of-decorators-in-python"],"_links":{"self":[{"href":"https:\/\/www.kaashivinfotech.com\/blog\/wp-json\/wp\/v2\/posts\/15651","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kaashivinfotech.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kaashivinfotech.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kaashivinfotech.com\/blog\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kaashivinfotech.com\/blog\/wp-json\/wp\/v2\/comments?post=15651"}],"version-history":[{"count":0,"href":"https:\/\/www.kaashivinfotech.com\/blog\/wp-json\/wp\/v2\/posts\/15651\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kaashivinfotech.com\/blog\/wp-json\/wp\/v2\/media\/15658"}],"wp:attachment":[{"href":"https:\/\/www.kaashivinfotech.com\/blog\/wp-json\/wp\/v2\/media?parent=15651"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kaashivinfotech.com\/blog\/wp-json\/wp\/v2\/categories?post=15651"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kaashivinfotech.com\/blog\/wp-json\/wp\/v2\/tags?post=15651"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}