I am using a decorator to extend certain classes and add some functionality to them, something like the following:
def useful_stuff(cls):
class LocalClass(cls):
def better_foo(self):
print('better foo')
return LocalClass
@useful_stuff
class MyClass:
def foo(self):
print('foo')
Unfortunaltely, MyClass is no longer pickleable due to the non global LocalClass
AttributeError: Can't pickle local object 'useful_stuff.<locals>.LocalClass'
To decorate a function with a class, we must use the @syntax followed by our class name above the function definition. Following convention, we will use camel-case for our class name. In the class definition, we define two methods: the init constructor and the magic (or dunder) call method.
Simply write the decorator name using the “@” symbol before the function definition as shown below. In the following script, the functionality of the my_func() function is extended using the my_decorator() function. Finally, you can also extend multiple functions using a single decorator.
In Python, we can extend a class to create a new class from the existing one. This becomes possible because Python supports the feature of inheritance. Using inheritance, we can make a child class with all the parent class's features and methods.
Decorators are a very powerful and useful tool in Python since it allows programmers to modify the behaviour of function or class. Decorators allow us to wrap another function in order to extend the behaviour of the wrapped function, without permanently modifying it.
To decorate this class in Python, we can either add new methods to the class or modify the existing ones, or do both. Also, there are two ways of doing so in Python, either by using a function decorator or by using a class decorator. Let’s see an example of each one by one. Decorate Class using Function Decorator
Now, we have to define a decorator in such a way that the add() function should also print the product of the numbers along with the sum. For this, we can create a decorator class. We can implement the __call__() method inside a class to implement the decorators.
Use callable classes as decorators by implementing the __call__ method. Pass the decorator arguments to the __init__ method. Did you find this tutorial helpful ?
To decorate the class using a function decorator accept the class as an argument, modify its code and return the class at the end. If the display method did not existed in the class, the newdisplay would have been added to the class as the display method.
You need to set the metadata so the subclass looks like the original:
def deco(cls):
class SubClass(cls):
...
SubClass.__name__ = cls.__name__
SubClass.__qualname__ = cls.__qualname__
SubClass.__module__ = cls.__module__
return SubClass
Classes are pickled by using their module and qualname to record where to find the class. Your class needs to be found in the same location the original class would have been if it hadn't been decorated, so pickle needs to see the same module and qualname. This is similar to what funcutils.wraps
does for decorated functions.
However, it would probably be simpler and less bug-prone to instead add the new methods directly to the original class instead of creating a subclass:
def better_foo(self):
print('better_foo')
def useful_stuff(cls):
cls.better_foo = better_foo
return cls
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With