A neat example, from the Learning Python book, it

class Tracer:
    
    def __init__(self, func):
        self.calls = 0
        self.func = func
        
    def __call__(self, *args):
        self.calls += 1
        print('Call {} to {}'.format(self.calls, self.func.__name__))
    
@Tracer
def spam(a, b):
    print(a + b)
    
for i in range(20):
    spam(i, i**2)

which, as you can see, tracks the number of times a function is called by using the @Tracer decorator. This functionality, is called Tracing Calls. This code outputs:

Call 1 to spam
0
Call 2 to spam
2
Call 3 to spam
6
Call 4 to spam
12
Call 5 to spam
20
Call 6 to spam
30
Call 7 to spam
42
Call 8 to spam
56
Call 9 to spam
72
Call 10 to spam
90
Call 11 to spam
110
Call 12 to spam
132
Call 13 to spam
156
Call 14 to spam
182
Call 15 to spam
210
Call 16 to spam
240
Call 17 to spam
272
Call 18 to spam
306
Call 19 to spam
342
Call 20 to spam
380