Classes in Python can be extended by inheritance. In Python 3 ability to make a class-decorator was added per PEP request.
Check out that you can make a type of inheritance from decorator to add something to method like in this example
To The Point
How to make your own class decorator? First you need a class definition so let's create one :
class MyFancyClass:
def __call__(self):
print("You were calling sir?!")
fancy_object = MyFancyClass()
fancy_object()
Now we can create our class decorator:
def fancy_class_decorator(cls):
old_init = cls.__init__
def new_init(self, *args, **kwargs):
old_init(self, *args, **kwargs)
print("here goes your additional code to init!")
cls.__init__ = new_init
return cls
And using decorator :
@fancy_class_decorator
class MyFancyClass:
def __call__(self):
print("You were calling sir?!")
fancy_object = MyFancyClass()
fancy_object()
While I was researching topic I've found that making a class-only fields that are not initialized within constructor can lead to a bad results.
Check out this:
def fancy_class_decorator(cls):
old_init = cls.__init__
def new_init(self, *args, **kwargs):
self.onevar = "fancy_decorator_before"
self.before = "fancy_decorator_before"
old_init(self, *args, **kwargs)
self.onevar = "fancy_decorator_after"
self.after = "fancy_decorator_after"
cls.__init__ = new_init
return cls
@fancy_class_decorator
class MyFancyClass:
onevar = "class"
before = "class"
after = "class"
def __call__(self):
print("onevar", self.onevar)
print("before", self.before)
print("after", self.after)
fancy_object = MyFancyClass()
fancy_object()
And then This:
def fancy_class_decorator(cls):
old_init = cls.__init__
def new_init(self, *args, **kwargs):
self.onevar = "fancy_decorator_before"
self.before = "fancy_decorator_before"
old_init(self, *args, **kwargs)
self.onevar = "fancy_decorator_after"
self.after = "fancy_decorator_after"
cls.__init__ = new_init
return cls
@fancy_class_decorator
class MyFancyClass:
def __init__(self):
self.onevar = "class"
self.before = "class"
self.after = "class"
def __call__(self):
print("onevar", self.onevar)
print("before", self.before)
print("after", self.after)
fancy_object = MyFancyClass()
fancy_object()
First example presents situation where you create a class-based fields which are not initialized within constructor of class.
Because we are making a decorator-inheritance over constructor, it automatically changes fields data.
Snippets
Replace old_method
with method you want to make decorator-inheritance on.
def class_decorator(cls):
old_method = cls.method
def new_method(self, *args, **kwargs):
old_method(self, *args, **kwargs)
cls.old_method = new_method
return cls
Acknowledgements
Auto-promotion:
Found related to post:
- PEP 3129 - Class decorators
- PEP 318 - Decorators for functions and methods
- PEPs Github Repo
- Krzysztof Żuraw Blog about Python class decorators
- Jonathan Fine tutorial on decorators
- Python class decorator
- Django-parsley decorators
Not related, but also time-worth:
Thanks!
That's it :) Comment, share or don't :)
If you have any suggestions what I should blog about in the next articles - please give me a hint :)
See you in the next episode! Cheers!
Comments
comments powered by Disqus