decorator pattern the print statement inside the fib function is just there to show where the execution fits relative to the profiling decorator remove it once you see it in action so as to not influence the actual time taken for the calculation profiling decorator initiated inside fib [time elapsed for - fibonacci number for in the class definitionwe see that the decorated function is saved as an attribute of the object during initialization thenin the call functionthe actual running of the function being decorated is wrapped in time requests just before returningthe profile value is printed to the console when the compiler comes across the @profilingdecorator_it initiates an object and passes in the function being wrapped as an argument to the constructor the returned object has the __call__(function as methodand as such duck typing will allow this object to be used as function alsonote how we used *args in the __call__(method' parameters to pass in arguments *args allows us to handle multiple arguments coming in this is called packingas all the parameters coming in are packed into the args variable thenwhen we call the stored function in the attribute of the decorating objectwe once again use *args this is called unpackingand it turns all the elements of the collection in args into individual arguments that are passed on to the function in question the decorator is unary function ( function that takes single argumentthat takes function to be decorated as its argument as you saw earlierit then returns function that is the same as the original function with some added functionality this means that all the code that interacts with the decorated function can remain the same as when the function was undecorated this allows us to stack decorators soin silly examplewe could profile our fibonacci function and then output the result string as html stacked_ fib py import time class profilingdecorator(object)def __init__(selff)print("profiling decorator initiated"self