如何在外部包中更改一个 class 供我使用?

How to change one class in an external package for my use?

我使用通过 pip 引入的外部包。

这个包的结构如下:

class OuterThing:
  field: Innerthing
  def outer_method1(self...

class InnerThing():
   def inner_method1(self,...
   def inner_method2(self,...
   def inner_method3(self,...

我只实例化 OuterThing 个对象(然后在内部实例化 InnerThing 个对象)。

我希望内部事物对象具有所有正常的字段和方法,只是inner_method1我需要自定义一些以供我使用。

最短的方法(即代码最少的方法)是什么?

不想如果可能的话将整个包复制到我的源代码树中,只需在运行时(但可能在所有实例化之前)将更改“注入”到指定的方法在 InnerThing.

Python 允许您通过将不同的函数指针分配给您要替换的函数来简单地 Monkey Patch 编写代码。只要您可以在运行时获取对 InnerThing 实例的引用,就可以做到这一点。

在你的情况下,似乎 OuterThing 确实引用了 InnerThing,所以你可以这样做:

def your_implementation_of_inner_method1(self, ...):
   # Do stuff

outerThing = OuterThing()
outerThing.field.inner_method1 = your_implementation_of_inner_method1

如果您想更深入地了解为什么这是可能的,我建议您查看 Python documentation for classes。 tl;dr 是方法实际上是对象,并作为字段存储在 class.

的实例中

在Python中,方法只是class对象的一个​​属性,恰好是一个以self作为第一个参数的函数。这意味着您可以轻松地用您自己的函数替换它,前提是您保持相同的签名。您甚至可以从自己的方法中调用原始方法:

# after having imported InnerThing
_orig_inner_method1 = InnerThing.inner_method1

def _patched_inner_method1(self, ...):
    # your own code
    ...
    _orig_inner_metho1(self, ...)   # eventually call the original method
    ...

InnerThing.inner_method1 = _patched_inner_method1

从那时起,创建的任何 InnerThing 对象都将使用您的修补方法。