Credit: Stephan Diehl, Robert E. Brewer
You need to add functionality to an existing class without changing the source code for that class. Specifically, you need to enrich all methods of the class, adding some extra functionality "around" that of the existing methods.
previously showed a way to solve this task for one method by writing a
closure that builds and applies a wrapper, exemplified by function
add_tracing_prints_to_method in that recipe's
Solution. This recipe generalizes that one, wrapping methods
throughout a class or hierarchy, directly or via a custom
you easily find all methods of an existing class, so you can
systematically wrap them all:
import inspect def add_tracing_prints_to_all_methods(class_object): for method_name, v in inspect.getmembers(class_object, inspect.ismethod): add_tracing_prints_to_method(class_object, method_name)
If you need to ensure that such wrapping applies to all methods of all classes in a whole hierarchy, the simplest way may be to insert a custom metaclass at the root of the hierarchy, so that all classes in the hierarchy will get that same metaclass. This insertion does normally need a minimum of "invasiveness"—placing a single statement
_ _metaclass_ _ = MetaTracer
in the body of that root class. Custom metaclass
MetaTracer is, however, quite easy to write:
class MetaTracer(type): def _ _init_ _(cls, n, b, d): super(MetaTracer, ...