Method decorators: As mentioned in one of this chapter’s notes, the timerdeco2.py module’s timer function decorator with decorator arguments that we wrote in the section Adding Decorator Arguments can be applied only to simple functions, because it uses a nested class with a __call__ operator overloading method to catch calls. This structure does not work for a class’s methods because the decorator instance is passed to self, not the subject class instance.
Rewrite this decorator so that it can be applied to both simple functions and methods in classes, and test it on both functions and methods. (Hint: see the section Class Blunders I: Decorating Methods for pointers.) Note that you will probably need to use function object attributes to keep track of total time, since you won’t have a nested class for state retention and can’t access nonlocals from outside the decorator code. As an added bonus, this makes your decorator usable on both Python 3.X and 2.X.
Class decorators: The Public/Private class decorators we wrote in module access2.py in this chapter’s first case study example will add performance costs to every attribute fetch in a decorated class. Although we could simply delete the @ decoration line to gain speed, we could also augment the decorator itself to check the __debug__ switch and perform no wrapping at all when the –O Python flag is passed on the command line—just as we did for the argument range-test decorators. That way, we can speed our program without changing its source, via command-line arguments (python –O main.py...). While we’re at it, we could also use one of the mix-in superclass techniques we studied to catch a few built-in operations in Python 3.X too. Code and test these two extensions.
Generalized argument validations: The function and method decorator we wrote in rangetest.py checks that passed arguments are in a valid range, but we also saw that the same pattern could apply to similar goals such as argument type testing, and possibly more. Generalize the range tester so that its single code base can be used for multiple argument validations. Passed-in functions may be the simplest solution given the coding structure here, though in more OOP-based contexts, subclasses that provide expected methods can often provide similar generalization routes as well.