banner



How To Create A Decorator In Python

half dozen. Decorators and Decoration

By Bernd Klein. Last modified: 01 Feb 2022.

Introduction

Decorators belong most probably to the near beautiful and most powerful design possibilities in Python, but at the same time the concept is considered by many as complicated to get into. To be precise, the usage of decorators is very like shooting fish in a barrel, just writing decorators tin be complicated, especially if you are not experienced with decorators and some functional programming concepts.

Even though it is the same underlying concept, we have two different kinds of decorators in Python:

  • Role decorators
  • Class decorators

A decorator in Python is any callable Python object that is used to alter a part or a class. A reference to a function "func" or a class "C" is passed to a decorator and the decorator returns a modified function or class. The modified functions or classes usually incorporate calls to the original part "func" or form "C".

You may likewise consult our affiliate on memoization with decorators.

decorators

If you like the paradigm above and if yous are too interested in image processing with Python, Numpy, Scipy and Matplotlib, you will definitely like our chapter on Paradigm Processing Techniques, it explains the whole process of the making-of of our decorator and at sign motion-picture show!

First Steps to Decorators

We know from our various Python preparation classes that at that place are some points in the definitions of decorators, where many beginners get stuck.

Therefore, we will innovate decorators by repeating some important aspects of functions. First you take to know or remember that function names are references to functions and that we can assign multiple names to the same function:

              def              succ              (              x              ):              return              10              +              1              successor              =              succ              successor              (              10              )            

OUTPUT:

OUTPUT:

This means that we have two names, i.eastward. "succ" and "successor" for the aforementioned function. The side by side important fact is that we can delete either "succ" or "successor" without deleting the function itself.

OUTPUT:

Functions inside Functions

The concept of having or defining functions inside of a function is completely new to C or C++ programmers:

              def              f              ():              def              thou              ():              print              (              "Hullo, it's me 'g'"              )              print              (              "Cheers for calling me"              )              print              (              "This is the role 'f'"              )              print              (              "I am calling 'thousand' now:"              )              g              ()              f              ()            

OUTPUT:

This is the part 'f' I am calling 'g' now: How-do-you-do, it'due south me 'g' Cheers for calling me            

Another example using "proper" return statements in the functions:

              def              temperature              (              t              ):              def              celsius2fahrenheit              (              10              ):              return              9              *              10              /              v              +              32              issue              =              "It'south "              +              str              (              celsius2fahrenheit              (              t              ))              +              " degrees!"              return              effect              print              (              temperature              (              xx              ))            

OUTPUT:

The following example is about the factorial function, which we previously defined as follows:

            def            factorial            (            north            ):            """ calculates the factorial of due north,                                      due north should be an integer and n <= 0 """            if            n            ==            0            :            return            1            else            :            return            n            *            factorial            (            north            -            i            )          

What happens if someone passes a negative value or a float number to this function? It will never end. You might go the idea to check that as follows:

            def            factorial            (            n            ):            """ calculates the factorial of n,                                      n should be an integer and due north <= 0 """            if            type            (            n            )            ==            int            and            north            >=            0            :            if            n            ==            0            :            render            1            else            :            render            northward            *            factorial            (            n            -            1            )            else            :            raise            TypeError            (            "n has to be a positive integer or zero"            )          

If y'all call this function with 4 '' for example, i.e. factorial (iv) '', the first thing that is checked is whether it is my positive integer. In principle, this makes sense. The "problem" at present appears in the recursion footstep. Now factorial (3) '' is chosen. This call and all others also cheque whether it is a positive whole number. But this is unnecessary: If you lot subtract the value one '' from a positive whole number, you get a positive whole number or `` 0 '' again. So both well-divers argument values for our part.

With a nested function (local role) ane can solve this problem elegantly:

            def            factorial            (            n            ):            """ calculates the factorial of n,                                      n should be an integer and n <= 0 """            def            inner_factorial            (            n            ):            if            n            ==            0            :            return            i            else            :            return            n            *            inner_factorial            (            due north            -            one            )            if            type            (            n            )            ==            int            and            northward            >=            0            :            return            inner_factorial            (            n            )            else            :            raise            TypeError            (            "n should be a positve int or 0"            )          

Functions as Parameters

If you solely look at the previous examples, this doesn't seem to be very useful. It gets useful in combination with 2 farther powerful possibilities of Python functions. Due to the fact that every parameter of a function is a reference to an object and functions are objects besides, we can pass functions - or better "references to functions" - as parameters to a role. Nosotros will demonstrate this in the next uncomplicated example:

              def              thousand              ():              impress              (              "Hi, it's me 'm'"              )              print              (              "Thanks for calling me"              )              def              f              (              func              ):              print              (              "Hi, it's me 'f'"              )              print              (              "I will phone call 'func' now"              )              func              ()              f              (              yard              )            

OUTPUT:

Hi, it'southward me 'f' I will call 'func' now Hi, it'south me 'g' Thanks for calling me            

Y'all may not exist satisfied with the output. 'f' should write that information technology calls '1000' and not 'func'. Of course, we need to know what the 'existent' name of func is. For this purpose, we can use the attribute __name__, as it contains this proper name:

              def              g              ():              impress              (              "Hi, it'south me '1000'"              )              print              (              "Thanks for calling me"              )              def              f              (              func              ):              print              (              "Hi, it's me 'f'"              )              print              (              "I will call 'func' now"              )              func              ()              print              (              "func's real proper name is "              +              func              .              __name__              )              f              (              g              )            

OUTPUT:

Hi, information technology'due south me 'f' I will call 'func' now Hi, it's me 'm' Thanks for calling me func's real proper name is chiliad            

The output explains what'due south going on once more. Another example:

              import              math              def              foo              (              func              ):              print              (              "The function "              +              func              .              __name__              +              " was passed to foo"              )              res              =              0              for              x              in              [              1              ,              ii              ,              ii.v              ]:              res              +=              func              (              10              )              return              res              impress              (              foo              (              math              .              sin              ))              print              (              foo              (              math              .              cos              ))            

OUTPUT:

The role sin was passed to foo ii.3492405557375347 The function cos was passed to foo -0.6769881462259364            

Functions returning Functions

The output of a function is also a reference to an object. Therefore functions tin can return references to function objects.

              def              f              (              x              ):              def              g              (              y              ):              return              y              +              x              +              3              return              g              nf1              =              f              (              one              )              nf2              =              f              (              3              )              print              (              nf1              (              ane              ))              print              (              nf2              (              1              ))            

OUTPUT:

The previous case looks very artificial and absolutely useless. We volition present now another language oriented example, which shows a more practical touch. Okay, still not a office which is useful the way it is. We write a function with the nearly self-explanatory name greeting_func_gen. So this function returns (or generates) functions which can be used to create people in different languages, i.e. German, French, Italian, Turkish, and Greek:

              def              greeting_func_gen              (              lang              ):              def              customized_greeting              (              name              ):              if              lang              ==              "de"              :              # German              phrase              =              "Guten Morgen "              elif              lang              ==              "fr"              :              # French              phrase              =              "Bonjour "              elif              lang              ==              "information technology"              :              # Italian              phrase              =              "Buongiorno "              elif              lang              ==              "tr"              :              # Turkish              phrase              =              "Günaydın "              elif              lang              ==              "gr"              :              # Greek              phrase              =              "Καλημερα "              else              :              phrase              =              "Hi "              return              phrase              +              name              +              "!"              return              customized_greeting              say_hi              =              greeting_func_gen              (              "tr"              )              print              (              say_hi              (              "Gülay"              ))              # this Turkish name means "rose moon" past the way            

OUTPUT:

It is getting more than useful and at the same time more mathematically oriented in the post-obit example. We will implement a polynomial "factory" function now. We will start with writing a version which tin create polynomials of degree two.

$$p(10) = ax^2 + bx + c$$

The Python implementation equally a polynomial factory office tin can be written similar this:

              def              polynomial_creator              (              a              ,              b              ,              c              ):              def              polynomial              (              ten              ):              return              a              *              x              **              2              +              b              *              x              +              c              render              polynomial              p1              =              polynomial_creator              (              2              ,              3              ,              -              1              )              p2              =              polynomial_creator              (              -              1              ,              2              ,              1              )              for              10              in              range              (              -              ii              ,              2              ,              1              ):              print              (              x              ,              p1              (              x              ),              p2              (              x              ))            

OUTPUT:

-2 i -seven -1 -ii -two 0 -1 1 1 4 2            

We can generalize our factory function and then that it tin can work for polynomials of capricious caste:

$$\sum_{k=0}^{n} a_{grand} \cdot x^{thou} = a_{n} \cdot x^{northward} + a_{northward-one} \cdot ten^{northward-i} + ... + a_{2} \cdot x^{ii} + a_{ane} \cdot x + a_{0} $$

              def              polynomial_creator              (              *              coefficients              ):              """ coefficients are in the grade a_n, ... a_1, a_0                                            """              def              polynomial              (              x              ):              res              =              0              for              index              ,              coeff              in              enumerate              (              coefficients              [::              -              1              ]):              res              +=              coeff              *              10              **              index              return              res              return              polynomial              p1              =              polynomial_creator              (              4              )              p2              =              polynomial_creator              (              two              ,              4              )              p3              =              polynomial_creator              (              i              ,              8              ,              -              1              ,              3              ,              2              )              p4              =              polynomial_creator              (              -              ane              ,              2              ,              1              )              for              ten              in              range              (              -              2              ,              two              ,              1              ):              print              (              ten              ,              p1              (              x              ),              p2              (              10              ),              p3              (              x              ),              p4              (              ten              ))            

OUTPUT:

-2 iv 0 -56 -7 -one 4 2 -9 -2 0 iv iv two 1 1 iv 6 13 2            

The function p3 implements, for example, the following polynomial:

$$p_3(x) = ten^{4} + eight \cdot x^{3} - x^{2} + 3 \cdot x + 2 $$

The polynomial function within of our decorator polynomial_creator can exist implemented more efficiently. We can factorize information technology in a way then that it doesn't demand any exponentiation.

Factorized version of a full general polynomial without exponentiation:

$$res = (...(a_{n} \cdot x + a_{north-1}) \cdot 10 + ... + a_{ane}) \cdot x + a_{0}$$

Implementation of our polynomial creator decorator avoiding exponentiation:

              def              polynomial_creator              (              *              coeffs              ):              """ coefficients are in the form a_n, a_n_1, ... a_1, a_0                                            """              def              polynomial              (              x              ):              res              =              coeffs              [              0              ]              for              i              in              range              (              one              ,              len              (              coeffs              )):              res              =              res              *              x              +              coeffs              [              i              ]              return              res              render              polynomial              p1              =              polynomial_creator              (              4              )              p2              =              polynomial_creator              (              two              ,              four              )              p3              =              polynomial_creator              (              1              ,              8              ,              -              1              ,              3              ,              ii              )              p4              =              polynomial_creator              (              -              1              ,              ii              ,              1              )              for              10              in              range              (              -              2              ,              2              ,              1              ):              impress              (              x              ,              p1              (              x              ),              p2              (              x              ),              p3              (              x              ),              p4              (              x              ))            

OUTPUT:

-2 4 0 -56 -7 -1 4 2 -9 -2 0 4 4 2 1 ane iv 6 13 2            

If you want to acquire more than most polynomials and how to create a polynomial grade, y'all tin continue with our chapter on Polynomials.

A Simple Decorator

Now we have everything ready to define our first unproblematic decorator:

              def              our_decorator              (              func              ):              def              function_wrapper              (              x              ):              print              (              "Earlier calling "              +              func              .              __name__              )              func              (              x              )              print              (              "Later on calling "              +              func              .              __name__              )              return              function_wrapper              def              foo              (              x              ):              print              (              "Hi, foo has been called with "              +              str              (              x              ))              print              (              "We call foo before ornamentation:"              )              foo              (              "Hi"              )              print              (              "We now decorate foo with f:"              )              foo              =              our_decorator              (              foo              )              print              (              "We call foo after ornament:"              )              foo              (              42              )            

OUTPUT:

Nosotros call foo before decoration: Hi, foo has been called with Howdy We now decorate foo with f: We call foo afterward ornamentation: Earlier calling foo Hi, foo has been called with 42 After calling foo            

If you expect at the output of the previous program, you tin can see what's going on. Subsequently the decoration "foo = our_decorator(foo)", foo is a reference to the 'function_wrapper'. 'foo' will be called inside of 'function_wrapper', merely before and after the call some additional code will be executed, i.e. in our case ii print functions.

Alive Python grooming

instructor-led training course

Upcoming online Courses

Enrol here

The Usual Syntax for Decorators in Python

The decoration in Python is usually not performed in the way we did it in our previous instance, fifty-fifty though the notation foo = our_decorator(foo) is catchy and easy to grasp. This is the reason, why we used it! You can too see a design trouble in our previous approach. "foo" existed in the aforementioned program in two versions, before decoration and subsequently decoration.

We will exercise a proper decoration now. The decoration occurrs in the line before the role header. The "@" is followed by the decorator function name.

We will rewrite now our initial case. Instead of writing the argument

          foo = our_decorator(foo)

we tin write

          @our_decorator        

But this line has to exist directly positioned in front of the decorated function. The complete example looks like this now:

              def              our_decorator              (              func              ):              def              function_wrapper              (              x              ):              print              (              "Before calling "              +              func              .              __name__              )              func              (              x              )              print              (              "Afterward calling "              +              func              .              __name__              )              return              function_wrapper              @our_decorator              def              foo              (              x              ):              print              (              "Hi, foo has been called with "              +              str              (              x              ))              foo              (              "Hi"              )            

OUTPUT:

Before calling foo Hi, foo has been called with Hi After calling foo            

We can decorate every other role which takes one parameter with our decorator 'our_decorator'. We demonstrate this in the post-obit. We have slightly changed our function wrapper, so that we can come across the upshot of the function calls:

              def              our_decorator              (              func              ):              def              function_wrapper              (              x              ):              print              (              "Earlier calling "              +              func              .              __name__              )              res              =              func              (              10              )              print              (              res              )              print              (              "Afterward calling "              +              func              .              __name__              )              return              function_wrapper              @our_decorator              def              succ              (              n              ):              render              north              +              1              succ              (              10              )            

OUTPUT:

Before calling succ xi Later calling succ            

It is likewise possible to decorate tertiary party functions, e.g. functions we import from a module. We tin't use the Python syntax with the "at" sign in this instance:

              from              math              import              sin              ,              cos              def              our_decorator              (              func              ):              def              function_wrapper              (              x              ):              print              (              "Before calling "              +              func              .              __name__              )              res              =              func              (              x              )              print              (              res              )              print              (              "After calling "              +              func              .              __name__              )              return              function_wrapper              sin              =              our_decorator              (              sin              )              cos              =              our_decorator              (              cos              )              for              f              in              [              sin              ,              cos              ]:              f              (              three.1415              )            

OUTPUT:

Earlier calling sin 9.265358966049026e-05 After calling sin Before calling cos -0.9999999957076562 Afterwards calling cos            

All in all, we tin can say that a decorator in Python is a callable Python object that is used to change a function, method or form definition. The original object, the i which is going to be modified, is passed to a decorator as an argument. The decorator returns a modified object, east.k. a modified role, which is bound to the name used in the definition.

The previous function_wrapper works merely for functions with exactly 1 parameter. We provide a generalized version of the function_wrapper, which accepts functions with capricious parameters in the following example:

              from              random              import              random              ,              randint              ,              choice              def              our_decorator              (              func              ):              def              function_wrapper              (              *              args              ,              **              kwargs              ):              print              (              "Before calling "              +              func              .              __name__              )              res              =              func              (              *              args              ,              **              kwargs              )              print              (              res              )              print              (              "After calling "              +              func              .              __name__              )              return              function_wrapper              random              =              our_decorator              (              random              )              randint              =              our_decorator              (              randint              )              choice              =              our_decorator              (              pick              )              random              ()              randint              (              3              ,              eight              )              choice              ([              4              ,              5              ,              6              ])            

OUTPUT:

Before calling random 0.3206237466802222 After calling random Before calling randint 6 Later calling randint Before calling pick 5 Afterward calling choice            

Use Cases for Decorators

Checking Arguments with a Decorator

In our affiliate most recursive functions we introduced the factorial office. Nosotros wanted to keep the function as simple as possible and nosotros didn't want to obscure the underlying thought, so we didn't contain whatever argument checks. So, if somebody called our role with a negative argument or with a float statement, our function would become into an countless loop.

The following programme uses a decorator function to ensure that the argument passed to the part factorial is a positive integer:

              def              argument_test_natural_number              (              f              ):              def              helper              (              ten              ):              if              blazon              (              x              )              ==              int              and              x              >              0              :              render              f              (              x              )              else              :              raise              Exception              (              "Argument is non an integer"              )              return              helper              @argument_test_natural_number              def              factorial              (              n              ):              if              n              ==              1              :              return              i              else              :              return              n              *              factorial              (              n              -              one              )              for              i              in              range              (              one              ,              10              ):              print              (              i              ,              factorial              (              i              ))              print              (              factorial              (              -              1              ))            

OUTPUT:

1 1 two two 3 6 4 24 5 120 6 720 seven 5040 8 40320 9 362880            

Counting Office Calls with Decorators

The post-obit case uses a decorator to count the number of times a function has been called. To be precise, we can use this decorator solely for functions with exactly one parameter:

              def              call_counter              (              func              ):              def              helper              (              x              ):              helper              .              calls              +=              1              return              func              (              10              )              helper              .              calls              =              0              return              helper              @call_counter              def              succ              (              ten              ):              render              x              +              1              print              (              succ              .              calls              )              for              i              in              range              (              ten              ):              succ              (              i              )              print              (              succ              .              calls              )            

OUTPUT:

Nosotros pointed out that nosotros can utilize our previous decorator only for functions, which accept exactly one parameter. Nosotros volition use the *args and **kwargs notation to write decorators which tin can cope with functions with an capricious number of positional and keyword parameters.

              def              call_counter              (              func              ):              def              helper              (              *              args              ,              **              kwargs              ):              helper              .              calls              +=              1              return              func              (              *              args              ,              **              kwargs              )              helper              .              calls              =              0              return              helper              @call_counter              def              succ              (              x              ):              render              ten              +              i              @call_counter              def              mul1              (              x              ,              y              =              1              ):              return              x              *              y              +              1              impress              (              succ              .              calls              )              for              i              in              range              (              10              ):              succ              (              i              )              mul1              (              iii              ,              4              )              mul1              (              4              )              mul1              (              y              =              iii              ,              x              =              2              )              impress              (              succ              .              calls              )              print              (              mul1              .              calls              )            

OUTPUT:

Decorators with Parameters

We define two decorators in the following lawmaking:

              def              evening_greeting              (              func              ):              def              function_wrapper              (              10              ):              impress              (              "Expert evening, "              +              func              .              __name__              +              " returns:"              )              return              func              (              x              )              return              function_wrapper              def              morning_greeting              (              func              ):              def              function_wrapper              (              x              ):              print              (              "Good morning, "              +              func              .              __name__              +              " returns:"              )              return              func              (              ten              )              return              function_wrapper              @evening_greeting              def              foo              (              ten              ):              print              (              42              )              foo              (              "Hi"              )            

OUTPUT:

Expert evening, foo returns: 42            

These two decorators are nearly the same, except for the greeting. We desire to add a parameter to the decorator to be capable of customizing the greeting, when we practise the ornamentation. Nosotros take to wrap another function around our previous decorator function to accomplish this. We can now easily say "Good Morning" in Greek:

              def              greeting              (              expr              ):              def              greeting_decorator              (              func              ):              def              function_wrapper              (              x              ):              print              (              expr              +              ", "              +              func              .              __name__              +              " returns:"              )              func              (              10              )              render              function_wrapper              return              greeting_decorator              @greeting              (              "καλημερα"              )              def              foo              (              x              ):              print              (              42              )              foo              (              "Hi"              )            

OUTPUT:

καλημερα, foo returns: 42            

If we don't want or cannot use the "at" decorator syntax, we can exercise it with role calls:

              def              greeting              (              expr              ):              def              greeting_decorator              (              func              ):              def              function_wrapper              (              x              ):              print              (              expr              +              ", "              +              func              .              __name__              +              " returns:"              )              return              func              (              x              )              return              function_wrapper              return              greeting_decorator              def              foo              (              x              ):              print              (              42              )              greeting2              =              greeting              (              "καλημερα"              )              foo              =              greeting2              (              foo              )              foo              (              "Hi"              )            

OUTPUT:

καλημερα, foo returns: 42            

Of course, we don't need the additional definition of "greeting2". We tin can direct apply the result of the call "greeting("καλημερα")" on "foo":

          foo = greeting("καλημερα")(foo)

The way we accept divers decorators so far hasn't taken into business relationship that the attributes

  • __name__ (proper noun of the part),
  • __doc__ (the docstring) and
  • __module__ (The module in which the role is defined)

of the original functions will exist lost after the decoration.

The following decorator will be saved in a file greeting_decorator.py:

          def greeting(func):     def function_wrapper(x):         """ function_wrapper of greeting """         print("Hi, " + func.__name__ + " returns:")         return func(x)     return function_wrapper        

We phone call it in the following program:

              from              greeting_decorator              import              greeting              @greeting              def              f              (              ten              ):              """ simply some silly part """              render              10              +              four              f              (              x              )              impress              (              "part proper noun: "              +              f              .              __name__              )              print              (              "docstring: "              +              f              .              __doc__              )              print              (              "module name: "              +              f              .              __module__              )            

OUTPUT:

How-do-you-do, f returns: function name: function_wrapper docstring:  function_wrapper of greeting  module name: greeting_decorator            

We get the "unwanted" results above.

We tin can save the original attributes of the function f, if we assign them inside of the decorator. Nosotros modify our previous decorator appropriately and save it as greeting_decorator_manually.py:

def greeting(func): def function_wrapper(x):     """ function_wrapper of greeting """     impress("How-do-you-do, " + func.__name__ + " returns:")     render func(x)     function_wrapper.__name__ = func.__name__     function_wrapper.__doc__ = func.__doc__     function_wrapper.__module__ = func.__module__     render function_wrapper        

In our main program, all we have to do is alter the import statement.

            from            greeting_decorator_manually            import            greeting          

Fortunately, we don't have to add all this code to our decorators to take these results. We can import the decorator "wraps" from functools instead and decorate our part in the decorator with it:

            from            functools            import            wraps            def            greeting            (            func            ):            @wraps            (            func            )            def            function_wrapper            (            ten            ):            """ function_wrapper of greeting """            print            (            "How-do-you-do, "            +            func            .            __name__            +            " returns:"            )            return            func            (            x            )            render            function_wrapper          

Classes instead of Functions

The call method

So far we used functions every bit decorators. Before we tin can define a decorator equally a class, nosotros have to introduce the __call__ method of classes. We mentioned already that a decorator is simply a callable object that takes a function as an input parameter. A role is a callable object, simply lots of Python programmers don't know that in that location are other callable objects. A callable object is an object which tin be used and behaves like a office just might not be a function. Information technology is possible to ascertain classes in a manner that the instances will be callable objects. The __call__ method is called, if the instance is called "similar a function", i.e. using brackets.

              class              A              :              def              __init__              (              cocky              ):              impress              (              "An instance of A was initialized"              )              def              __call__              (              self              ,              *              args              ,              **              kwargs              ):              print              (              "Arguments are:"              ,              args              ,              kwargs              )              x              =              A              ()              print              (              "now calling the case:"              )              x              (              three              ,              iv              ,              ten              =              11              ,              y              =              10              )              print              (              "Let'due south telephone call it again:"              )              x              (              3              ,              4              ,              x              =              11              ,              y              =              x              )            

OUTPUT:

An instance of A was initialized now calling the instance: Arguments are: (iii, 4) {'x': xi, 'y': ten} Let's call it once again: Arguments are: (3, iv) {'x': 11, 'y': 10}            

We tin write a class for the fibonacci function by using the __call__ method:

              grade              Fibonacci              :              def              __init__              (              self              ):              self              .              enshroud              =              {}              def              __call__              (              cocky              ,              n              ):              if              north              non              in              self              .              cache              :              if              n              ==              0              :              self              .              cache              [              0              ]              =              0              elif              n              ==              one              :              self              .              cache              [              1              ]              =              1              else              :              self              .              enshroud              [              northward              ]              =              self              .              __call__              (              n              -              1              )              +              self              .              __call__              (              north              -              ii              )              return              cocky              .              cache              [              n              ]              fib              =              Fibonacci              ()              for              i              in              range              (              xv              ):              print              (              fib              (              i              ),              end              =              ", "              )            

OUTPUT:

0, 1, ane, 2, 3, 5, 8, thirteen, 21, 34, 55, 89, 144, 233, 377,            

You tin discover further information on the __call__ method in the affiliate Magic Functions of our tutorial.

Using a Form equally a Decorator

We will rewrite the following decorator every bit a grade:

              def              decorator1              (              f              ):              def              helper              ():              print              (              "Decorating"              ,              f              .              __name__              )              f              ()              return              helper              @decorator1              def              foo              ():              print              (              "inside foo()"              )              foo              ()            

OUTPUT:

Decorating foo inside foo()            

The following decorator implemented as a form does the same "job":

              grade              decorator2              :              def              __init__              (              self              ,              f              ):              self              .              f              =              f              def              __call__              (              cocky              ):              print              (              "Decorating"              ,              self              .              f              .              __name__              )              self              .              f              ()              @decorator2              def              foo              ():              print              (              "inside foo()"              )              foo              ()            

OUTPUT:

Decorating foo inside foo()            

Both versions return the aforementioned output.

Live Python training

instructor-led training course

Upcoming online Courses

Enrol hither

Source: https://python-course.eu/advanced-python/decorators-decoration.php

Posted by: andraderessivoisin1962.blogspot.com

0 Response to "How To Create A Decorator In Python"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel