Skip to content

Instantly share code, notes, and snippets.

@andgineer
Last active April 9, 2020 11:15
Show Gist options
  • Save andgineer/026a617528c5740da24ec984ac282ee6 to your computer and use it in GitHub Desktop.
Save andgineer/026a617528c5740da24ec984ac282ee6 to your computer and use it in GitHub Desktop.
Python decorator class that works for standalone functions and for object methods
class UniversalDecorator:
""" Good for standalone functions as well as for object methods """
def __init__(self, orig_func):
self.orig_func = orig_func
def __call__(self, *args):
""" For standalone function decoration """
return self.orig_func(*args)
def __get__(self, wrapped_instance, owner):
""" For object method decoration.
It will detect __get__ as descriptor protocol.
So __get__ should return the actual method.
"""
print(wrapped_instance.name)
return WrapperHelper(self, wrapped_instance) # pass decorator instance and decorated object instance
class WrapperHelper:
""" Callable that store wrapped class instance and decorator instance """
def __init__(self, decorator_instance, wrapped_instance):
self.decorator_instance = decorator_instance
self.wrapped_instance = wrapped_instance
def __call__(self, *args, **kwargs):
""" Call func from decorator as object method - add decorated object instance we saved """
return self.decorator_instance(self.wrapped_instance, *args, **kwargs)
class ClassToWrap:
name="123"
def __init__(self):
pass
@UniversalDecorator
def func_to_wrap(self):
self.name += '!'
print(self.name)
return self.name
u = ClassToWrap()
u.func_to_wrap()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment