# class decorators act in the same way as a function decorator
# but a class can maintain and update a state
class CountCalls:
def __init__(self, func): #class decorator __init__ takes func
self.func = func
self.num_calls = 0 #keep tract of how many times func got executed
def __call__(self, *args, **kwargs):
self.num_calls += 1
print(f'This is executed {self.num_calls} times')
return self.func(*args, **kwargs)
@CountCalls
def say_hello():
print('Hello')
say_hello()
# This is executed 1 times
# Hello
say_hello()
# This is executed 2 times
# Hello
# class decorator
import random
# changes the properties of a function to a class instance
class Eliphant:
def __init__(self,funct):
self._funct = funct
#all return values are storredin momory
self._memory = []
def __call__(self):
returnvalue = self._funct()
self._memory.append(returnvalue)
return returnvalue
def memory(self):
return self._memory
@Eliphant
def random_odd():
return random.choice([1,3,5,7,9])
print(random_odd())
print(random_odd.memory())
print(random_odd())
print(random_odd.memory())
# I dont know whether the term "class decorator" is referring to
# using decorators on a class or using a class as a decorator
# so heres both!
## Using a class as a decorator ##
class TestDecorator:
# This is called when used, func is the function or class provided:
def __init__(self, func):
def wrapper(message):
print("Wrapper Calling: ", func(message))
return wrapper
@TestDecorator
def abc(message):
return message.upper()
## Using a decorator on a class ##
def TestDecorator(provided_class):
print("Given class: ", provided_class)
return provided_class
@TestDecorator
class abc: ...
# Here is an example from https://wiki.python.org/moin/PythonDecorators#Examples
@classmethod
def foo (arg1, arg2):
....
# https://wiki.python.org/moin/PythonDecoratorLibrary has more examples
# Python program showing
# use of __call__() method
class MyDecorator:
def __init__(self, function):
self.function = function
def __call__(self):
# We can add some code
# before function call
self.function()
# We can also add some code
# after function call.
# adding class decorator to the function
@MyDecorator
def function():
print("GeeksforGeeks")
function()
class Test(object):
def _decorator(foo):
def magic( self ) :
print "start magic"
foo( self )
print "end magic"
return magic
@_decorator
def bar( self ) :
print "normal call"
test = Test()
test.bar()