{"id":843,"date":"2014-09-22T01:04:37","date_gmt":"2014-09-22T05:04:37","guid":{"rendered":"http:\/\/qxf2.com\/blog\/?p=843"},"modified":"2014-09-22T06:11:09","modified_gmt":"2014-09-22T10:11:09","slug":"python-decorators","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/python-decorators\/","title":{"rendered":"Understanding Python decorators"},"content":{"rendered":"<p><strong>Problem:<\/strong>\u00a0Some testers shy away from unit testing because they are uncomfortable with the concept of annotations.<\/p>\n<hr>\n<h3>Why this post?<\/h3>\n<p>We often stop learning a topic when we need to apply a concept that we are not fully comfortable with. I noticed this pattern in testers when it came to unit testing. A lot of unit testing frameworks, like JUnit and PyUnit, make use of annotations. Testers who are uncomfortable with the concept of annotations are less inclined to learn unit testing. With this blog, we aim to clarify annotations for testers. <a href=\"http:\/\/www.qxf2.com\/?utm_source=annotations_decorators&#038;utm_medium=click&#038;utm_campaign=From%20blog\">We<\/a> hope this post helps you in learning and exploring unit testing frameworks.  <\/p>\n<p>NOTE: In the Python world, annotations are called <a href=\"https:\/\/wiki.python.org\/moin\/PythonDecorators\">decorators<\/a>. <\/p>\n<hr>\n<h3>What is a decorator?<\/h3>\n<p>Decorators are a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Metaprogramming\">metaprogramming<\/a> feature that lets you modify the language itself. A decorator is basically a wrap function. It takes a function as an argument and returns a replacement function. In general, a decorator is used to modify the behavior of function or classes and perform some additional actions on it. <u>Do not worry if you did not relate to this semi-technical definition.<\/u> In this post I provide an example of where we humans naturally use the concept of decorators outside of code. I&#8217;ll also give some scenarios where you can use decorators. <\/p>\n<hr>\n<h3> Decorators in the real world:<\/h3>\n<p>When I think of decorators in the real world, I think of a gun. What?? A Gun?! Before you think of shooting me let me clarify. There are a lot of accessories you can use with a gun like silencers, flashlights, laser scopes, stocks, pistol grips, etc.<br \/>\n<a href=\"http:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/qxf2-gun-decorator1.jpg\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/qxf2-gun-decorator1-1024x723.jpg\" alt=\"Gun with silencer\" width=\"474\" height=\"334\" class=\"aligncenter size-large wp-image-1606\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/qxf2-gun-decorator1-1024x723.jpg 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/qxf2-gun-decorator1-300x212.jpg 300w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/a><br \/>\nNow think of a gun which is wrapped with a silencer. The silencer modifies the behavior of the gun and performs some additional action like suppressing the noise. The silencer extends the functionality of gun without modifying it. It makes it easy to turn on and turn off the additional features.<br \/>\n<a href=\"http:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/qxf2_decorator_cartoon.jpg\" data-rel=\"lightbox-image-1\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/qxf2_decorator_cartoon-1024x666.jpg\" alt=\"Python decorator shooting cartoon\" width=\"474\" height=\"308\" class=\"aligncenter size-large wp-image-1642\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/qxf2_decorator_cartoon-1024x666.jpg 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2014\/09\/qxf2_decorator_cartoon-300x195.jpg 300w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<hr>\n<h3>Why use decorators at all?<\/h3>\n<p>Key reasons to use decorators are:<br \/>\n1. Improve code readability<br \/>\n2. Extend functionality of a function<\/p>\n<p><strong>1. Improve code readability:<\/strong><br \/>\nUsing Python decorators, we can make the code look cleaner. Consider the below example<\/p>\n<pre lang=\"python\">def addSixtyFour(f):\r\n    def inner():\r\n        return f() +64\r\n    return inner\r\n\r\ndef foo():\r\n    return 5\r\n\r\nfoo = addSixtyFour(foo)\r\nprint foo()\r\n<\/pre>\n<p>With the addition of the @ decoration operator, you now get the same result instead of using <em>foo = addSixtyFour(foo)<\/em><\/p>\n<pre lang=\"python\">def addSixtyFour(f):\r\n    def inner():\r\n        return f() +64\r\n    return inner\r\n\r\n@ addSixtyFour\r\ndef foo():\r\n    return 5\r\n\r\nprint foo()\r\n<\/pre>\n<p>Python replaces replaces foo() function with the decorated function addSixtyFour(). The decorated function addSixtyFour() has access to foo() in the form of <strong><em>f<\/em><\/strong>. Without decorators we have to do something much less elegant to achieve the same thing.<\/p>\n<p><strong>2. Extend functionality of a function:<\/strong><br \/>\nDecorators are ideally suited when you want to extend the functionality of function without modifying the function. It makes sense to use decorators if we don&#8217;t want to change the original function. Reverting back to the old functionality is easy. To revert back to the old functionality, just remove the decorator.<\/p>\n<hr>\n<h3>Frequently used decorators<\/h3>\n<p>In this section I cover a few frequently used decorators. For the examples below, instead of decorating a function with another function we will decorate it with a class. The object returned by the decorator can be used as a function which basically means it must be callable. So any classes we use as decorators must implement __call__ method. We also need to have __init__ method so that it can take the target function as a first-class object into the class.<\/p>\n<p><strong>NOTE:<\/strong> If you have forgotten to implement the __call__ method, you will see the error message: <strong>TypeError: $decorator_name object is not callable<\/strong><\/p>\n<p><u><strong>Example 1: Try catch<\/strong><\/u><br \/>\nIn the below example, I have used a decorator called &#8220;errorHandler&#8221; to handle the exception related to division by zero<\/p>\n<pre lang=\"python\">class errorHandler(object):\r\n  def __init__(self, f):\r\n    self.f = f\r\n\r\n  def __call__(self, *args):\r\n    try:\r\n      return self.f(*args)\r\n    except Exception, e:\r\n      print \"Error: %s\" % (e)\r\n\r\n@errorHandler\r\ndef divide(x):\r\n  return 1 \/ x\r\n\r\ndivide(0)\r\n<\/pre>\n<p><u><strong>Example 2: Entry exit<\/strong><\/u><br \/>\nIf you want any function to perform some actions at entry and exit of the function you can use a decorator similar to this.<\/p>\n<pre lang=\"python\">\r\nclass entryExit(object):\r\n\r\n    def __init__(self, f):\r\n        self.f = f\r\n\r\n    def __call__(self):\r\n        print \"Entering\", self.f.__name__\r\n        self.f()\r\n        print \"Exiting\", self.f.__name__\r\n\r\n@entryExit\r\ndef func1():\r\n    print \"inside func1()\"\r\n\r\n@entryExit\r\ndef func2():\r\n    print \"inside func2()\"\r\n\r\nfunc1()\r\nfunc2()\r\n<\/pre>\n<p>The decorated functions now have the &#8220;Entering&#8221; and &#8220;Exiting&#8221; statements around the call. The constructor stores the argument, which is the function object. In the call, we use the __name__ attribute of the function to display that function&#8217;s name, then call the function itself.<\/p>\n<p><u><strong>Example 3: Unittest skip decorator<\/strong><\/u><br \/>\nUnittest supports skipping individual test methods and even whole classes of tests. Skipping a test is simply a matter of using the skip() decorator or one of its conditional variants like skipIf() and skipUnless().<\/p>\n<pre lang=\"python\">\r\nimport unittest\r\nclass MyTestCase(unittest.TestCase):\r\n\r\n    @unittest.skip(\"demonstrating skipping\")\r\n    def testSkip(self):\r\n        self.fail(\"shouldn't happen\")\r\n\r\n    @unittest.skipIf(True,\"skip function since it is true\")\r\n    def testSkipIf(self):\r\n        # Test that work if condition is false.\r\n        pass\r\n\r\n    @unittest.skipUnless(False, \"skip function since it is False\")\r\n    def testSkipUnless(self):\r\n        # Test that work unless condition is True.\r\n        pass\r\n    \r\nif __name__ == '__main__':\r\n    unittest.main()\r\n<\/pre>\n<hr>\n<p>We hope this post de-mystified Python decorators for you. As always, we are happy to clarify any questions you may have. Fire away!<\/p>\n<hr>\n","protected":false},"excerpt":{"rendered":"<p>Problem:\u00a0Some testers shy away from unit testing because they are uncomfortable with the concept of annotations. Why this post? We often stop learning a topic when we need to apply a concept that we are not fully comfortable with. I noticed this pattern in testers when it came to unit testing. A lot of unit testing frameworks, like JUnit and [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[38,15,18],"tags":[],"class_list":["post-843","post","type-post","status-publish","format-standard","hentry","category-automation","category-how-to","category-python"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=843"}],"version-history":[{"count":53,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/843\/revisions"}],"predecessor-version":[{"id":1643,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/843\/revisions\/1643"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}