[英]What is the proper way to add an attribute to a base class in a Python library and have it inherited?
I am trying to extend a Python library to add functionality I desire. 我正在尝试扩展Python库以添加所需的功能。 The library provides a number of HTML form objects (such as Textbox
, Dropdown
, Checkbox
, etc.), all derived from an Input
object. 该库提供了许多HTML表单对象(例如Textbox
, Dropdown
, Checkbox
等),它们都是从Input
对象派生的。 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
类的原始源代码,添加我想要的属性。 Input
and adds my attribute, and then create a bunch of new classes that inherit Textbox
, Dropdown
, and my new Input
class. 创建一个继承Input
并添加我的属性的新类,然后创建一堆继承Textbox
, Dropdown
和我新的Input
类的新类。 Textbox
, Dropdown
, etc. with the attribute. 使用属性为Textbox
, Dropdown
等创建新类。 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. 解决方案1是最简单,最简单的方法,但从本质上讲是错误的,而其他两个似乎比该任务所需要的工作和代码重复更多。
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. 现在,所有现有的和将来的Input
实例(以及所有Input
子类的实例)都additional_method
了additional_method
。
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. 这对于添加方法时甚至可能还不存在或您可能不知道的Input
任何将来子类也适用,因此,比创建替代继承层次结构更好(即更通用),您可以然后必须维护并与上游更改保持同步。
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. 注意:在仅因为它包含短语“ monkey patching”而进行否决投票之前,请考虑一下猴子补丁不一定是危险/脆弱的,并且在许多语言中都是头等舱(如“尊敬的”)功能。
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: 这是一个只包含您额外属性的类,并将该类添加到Textbox, Dropdown, Checkbox...
的子类的父类中Textbox, Dropdown, Checkbox...
如下所示:
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. 编辑:在第三方库的情况下,基于@Veedrac注释。
If there are a lot of classes you could dynamically apply a mixin: 如果有很多类,则可以动态应用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
. 可以将place_to_export
定义为import this_module as place_to_export
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.