class Tracer:
    def __init__(self, aClass):               # W momencie dekoracji @
        self.aClass = aClass                  # Użycie atrybutu instancji
    def __call__(self, *args):                # W momencie tworzenia instancji
        self.wrapped = self.aClass(*args)     # JEDNA (OSTATNIA) INSTANCJA NA KLASĘ!
        return self
    def __getattr__(self, attrname):
        print('Trace:', attrname)
        return getattr(self.wrapped, attrname)

@Tracer                                       # Wywołuje __init__
class Hack:                                   # Jak: Hack = Tracer(Hack)
    def display(self):
        print('Hakować!' * 3)

work = Hack()                                 # Wywołuje __call__
work.display()                                # Wywołuje __getattr__

@Tracer
class Person:                                 # Person = Tracer(Person)
    def __init__(self, name):                 # Klasa Wrapper dowiązana do Person
        self.name = name

bob = Person('Robert')                        # Obiekt bob jest tak naprawdę instancją Wrapper
print(bob.name)                               # Wrapper osadza Person
Anna = Person('Anna')
print(anna.name)                              # Obiekt anna nadpisuje obiekt bob
print(bob.name)                               # UPS: teraz obiekt bob nazywa się 'Anna'!


