Chapter 9. Metaprogramming
One of the most important mantras of software development is “don’t repeat yourself.”
That is, any time you are faced with a problem of creating highly repetitive
code (or cutting or pasting source code), it often pays to look for a more elegant
solution. In Python, such problems are often solved under the category of “metaprogramming.” In
a nutshell, metaprogramming is about creating functions and classes whose main goal is to
manipulate code (e.g., modifying, generating, or wrapping existing code). The
main features for this include decorators, class decorators, and metaclasses. However,
a variety of other useful topics—including signature objects, execution of code with exec(),
and inspecting the internals of functions and classes—enter the picture. The main
purpose of this chapter is to explore various metaprogramming techniques and to give
examples of how they can be used to customize the behavior of Python to your own whims.
9.1. Putting a Wrapper Around a Function
Problem
You want to put a wrapper layer around a function that adds extra processing (e.g., logging, timing, etc.).
Solution
If you ever need to wrap a function with extra code, define a decorator function. For example:
importtimefromfunctoolsimportwrapsdeftimethis(func):'''Decorator that reports the execution time.'''@wraps(func)defwrapper(*args,**kwargs):start=time.time()result=func(*args,**kwargs)end=time.time()(func.__name__,end-start)returnresultreturn ...