简体   繁体   English

将属性添加到Python库中的基类并继承该属性的正确方法是什么?

[英]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表单对象(例如TextboxDropdownCheckbox等),它们都是从Input对象派生的。 I want to add an additional attribute to all of these derived objects. 我想向所有这些派生对象添加一个附加属性。 What is the proper way of proceeding? 正确的处理方法是什么?

I can: 我可以:

  1. Modify the original source code for the Input class, adding the attribute I want. 修改Input类的原始源代码,添加我想要的属性。
  2. Create a new class that inherits Input and adds my attribute, and then create a bunch of new classes that inherit Textbox , Dropdown , and my new Input class. 创建一个继承Input并添加我的属性的新类,然后创建一堆继承TextboxDropdown和我新的Input类的新类。
  3. Create new classes for Textbox , Dropdown , etc. with the attribute. 使用属性为TextboxDropdown等创建新类。

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_methodadditional_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.

相关问题 Python Abstract 调用基类中导入库的正确方法 - Python Abstract Proper Way of Calling Library Imported in Base Class 如何将_not_继承的属性添加到python * class *? - How to add attribute to python *class* that is _not_ inherited? Python-自动更新继承的类别中的基础类别属性(别名) - Python - Automatically update base class attribute (alias) in inherited class Python继承的基类变量 - Python inherited base class variables 有没有办法用 mypy 覆盖 python 中继承的 class 属性类型? - Is there any way to override inherited class attribute type in python with mypy? OOP Python向基类添加一些属性吗? - OOP Python add some attribute to the base class? 访问python类变量的正确方法是什么? - What is the proper way to access python class variables? When using Generics types, how can I call an Attribute of an inherited class on the Base class instance with Python / Django? - When using Generics types, how can I call an Attribute of an inherited class on the Base class instance with Python / Django? 在 python 中使用 super 调用父 class 的实例属性的正确方法 - Proper way to call the instance attribute of the parent class using super in python Python:将属性添加到实例,使其出现在类中 - Python: add attribute to instance, have it appear in class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM