Note
Click here to download the full example code
Example: decorating specified methods of a custom class with custom decoratorsΒΆ
This example shows how to decorate methods of a custom class with custom decorators.
import time
from pydeco import Decorator, MethodsDecorator
Create timer decorator
class Timer(Decorator):
"""Timer decorator."""
def __init__(self, *args, **kwargs):
self.run = 0
self.run_by_func = dict()
self.total_runtime = 0
Decorator.__init__(self, *args, **kwargs)
def __repr__(self):
"""Return the string representation."""
return ('Timer(run={}, run_by_func={}, total_runtime={:2.2f} ms)'
.format(self.run, self.run_by_func, self.total_runtime))
def wrapper(self, instance, func, *args, **kwargs):
"""Wrap input instance method with runtime measurement."""
# increment run attributes
self.run += 1
if func.__name__ not in self.run_by_func:
self.run_by_func[func.__name__] = 1
else:
self.run_by_func[func.__name__] += 1
# save current time
ts = time.time()
# call `func` on inputs
outs = func(instance, *args, **kwargs)
# compute elapsed time
te = time.time()
runtime = (te - ts) * 1000
# Update total runtime of timer
self.total_runtime += runtime
print('[Log] runtime {!r} : {:2.2f} ms'.format(func.__name__, runtime))
# return outputs of `func`
return outs
Create custom decorators
class Decorator1(Decorator):
"""Decorator 1."""
def __init__(self, *args, **kwargs):
Decorator.__init__(self, *args, **kwargs)
def wrapper(self, instance, func, *args, **kwargs):
"""Wrap input instance method with the herebelow code."""
print('[Decorator 1] -> decorating {}.{}'.format(
instance._Wrapper__wrapped_class.__name__, func.__name__))
return func(instance, *args, **kwargs)
class Decorator2(Decorator):
"""Decorator 2."""
def __init__(self, *args, **kwargs):
Decorator.__init__(self, *args, **kwargs)
def wrapper(self, instance, func, *args, **kwargs):
"""Wrap input instance method with the herebelow code."""
print('[Decorator 2] -> decorating {}.{}'.format(
instance._Wrapper__wrapped_class.__name__, func.__name__))
return func(instance, *args, **kwargs)
Create custom class
timer = Timer()
class MyClass():
"""Custom class."""
def __init__(self, *args, **kwargs):
pass
@timer
def method_1(self, *args, **kwargs):
print('Run method 1')
@timer
def method_2(self, *args, **kwargs):
print('Run method 2')
@timer
def method_3(self, *args, **kwargs):
print('Run method 3')
Test
# Without custom decorators
# -----------------------------------------------------------------------------
# instantiate the class
instance = MyClass()
# run methods
instance.method_1()
instance.method_2()
instance.method_3()
# With custom decorators for the respective methods
# -----------------------------------------------------------------------------
# decorate the class
MyClass_deco = MethodsDecorator(
mapping={
Decorator1(): ['method_1', 'method_2'],
Decorator2(): ['method_1', 'method_3']
})(MyClass)
# instantiate the class
instance = MyClass_deco()
# run methods
instance.method_1()
instance.method_2()
instance.method_3()
Out:
Run method 1
[Log] runtime 'method_1' : 0.11 ms
Run method 2
[Log] runtime 'method_2' : 0.03 ms
Run method 3
[Log] runtime 'method_3' : 0.06 ms
[Decorator 2] -> decorating MyClass.method_1
[Decorator 1] -> decorating MyClass.method_1
Run method 1
[Log] runtime 'method_1' : 0.03 ms
[Decorator 1] -> decorating MyClass.method_2
Run method 2
[Log] runtime 'method_2' : 0.08 ms
[Decorator 2] -> decorating MyClass.method_3
Run method 3
[Log] runtime 'method_3' : 0.04 ms
Total running time of the script: ( 0 minutes 0.022 seconds)