File: decorator2.py

"""
Class decorator that prints a trace message
for every access to an instance's attributes
made from outside the class's methods; access
within methods proceeds normally without trace
"""


def Tracer(aClass):                                   # on @decorator
    class Wrapper:
        def __init__(self, *args, **kargs):           # on instance creation
            self.wrapped = aClass(*args, **kargs)     # use enclosing scope name 
        def __getattr__(self, attrname):
            print 'Trace:', attrname                  # catches all but .wrapped 
            return getattr(self.wrapped, attrname)    # delegate to wrapped obj
    return Wrapper


"""
class Tracer:
    def __init__(self, aClass):               # on @decorator
        self.aClass = aClass                  # use instance attribute
    def __call__(self, *args):                # on instance creation
        self.wrapped = self.aClass(*args)     # ONE (LAST) INSTANCE PER CLASS!
        return self
    def __getattr__(self, attrname):
        print 'Trace:', attrname
        return getattr(self.wrapped, attrname)
"""


if __name__ == '__main__':
    
    @Tracer                   
    class Spam:                                    # like: Spam = Tracer(Spam)
        def display(self):                         # Spam is rebound to Wrapper
            print 'Spam!' * 8

    @Tracer
    class Person:                                  # Person = Tracer(Person)
        def __init__(self, name, hours, rate):     # Wrapper bound to Person
            self.name = name
            self.hours = hours
            self.rate = rate                       # in-method access not traced
        def pay(self):
            return self.hours * self.rate

    food = Spam()                                  # triggers Wrapper()
    food.display()                                 # triggers __getitem__

    bob = Person('Bob', 40, 50)                    # bob is really a Wrapper
    print bob.name                                 # Wrapper embeds a Person
    print bob.pay()

    print
    sue = Person('Sue', 60, 100)
    print sue.name
    print sue.pay()
    print bob.name
    print bob.pay()


    """
    Trace: display
    Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
    Trace: name
    Bob
    Trace: pay
    2000

    Trace: name
    Sue
    Trace: pay
    6000
    Trace: name
    Bob
    Trace: pay
    2000
    """



[Home page] Books Code Blog Python Author Train Find ©M.Lutz