I am trying to extend a Python library to add functionality I desire. The library provides a number of HTML form objects (such as Textbox
, Dropdown
, Checkbox
, etc.), all derived from an Input
object. I want to add an additional attribute to all of these derived objects. What is the proper way of proceeding?
I can:
Input
class, adding the attribute I want. Input
and adds my attribute, and then create a bunch of new classes that inherit Textbox
, Dropdown
, and my new Input
class. Textbox
, Dropdown
, etc. with the attribute. Solution 1 is the easiest and simplest, but is inherently wrong, whereas the other two seem like much more work and code-repetition than this task should call for.
Is there a solution I'm missing?
The 4th solution is monkey patching and might be a good idea. Before you try this, make sure this won't break anything now or in the future:
def additional_method(self, arg):
print("hello", arg)
Input.additional_method = additional_method
or for short stuff:
Input.additional_method = lambda self, arg: do_something(arg)
now all existing and future Input
instances (and therefore instances of all Input
subclasses) have an additional_method
attached to them.
This works also for any future subclasses of Input
that might not even exist yet, or you might not be aware of, at the time of adding the method, so is therefore better (ie more generic) than creating an alternative inheritance hierarchy, which you'll have to then maintain and keep in sync with upstream changes.
NOTE: before you downvote just because it contains the phrase "monkey patching", consider that monkey patching doesn't have to be dangerous/fragile, and is a first class (as in "respected") feature in many languages.
You can use a mixin (multiple inheritance). It's a class that just contains your extra attribute, and add this class to the parent class of a subclass of Textbox, Dropdown, Checkbox...
like this:
from ... import TextBox
class Mixin:
def __init__(self):
self.new_attribude = ...
class TextBox_with_new_attribute(Mixin, TextBox):
pass
But, it depends tightly on your goals...
Edit: base on @Veedrac comment, in case of third party library.
If there are a lot of classes you could dynamically apply a mixin:
for cls in list_of_classes_to_patch:
patched = type(cls.__name__, (my_mixin, cls), {})
setattr(place_to_export, cls.__name__, patched)
place_to_export
can be defined as import this_module as place_to_export
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.