class tracer:
    def __init__(self, func):          # Zapamiętanie oryginalnej funkcji, zainicjowanie licznika
        self.calls = 0
        self.func  = func
    def __call__(self, *args):         # Przy późniejszych wywołaniach: dodanie kodu, uruchomienie oryginalnej funkcji
        self.calls += 1
        print(f'wywołanie {self.calls} to {self.func.__name__}')
        return self.func(*args)

@tracer                                # Równoważne wywołaniu hack = tracer(hack)
def hack(a, b, c):                     # Opakowanie funkcji hack w obiekt dekoratora
    return a + b + c

if __name__ == '__main__':
    print(hack(1, 2, 3))               # Naprawdę wywołuje obiekt opakowujący tracer
    print(hack('a', 'b', 'c'))         # Wywołuje __call__ w klasie

