Monkey-patch Python类

时间:2010-09-21 23:28:22

标签: python monkeypatching

我有一个班级,位于一个单独的模块中,我无法改变。

from module import MyClass

class ReplaceClass(object)
  ...

MyClass = ReplaceClass

除了这个文件之外,这不会改变MyClass。但是,如果我要添加这样的方法

def bar():
   print 123

MyClass.foo = bar

这将起作用,foo方法将在其他地方可用。

如何完全替换课程?

4 个答案:

答案 0 :(得分:56)

import module
class ReplaceClass(object):
    ....
module.MyClass = ReplaceClass

答案 1 :(得分:28)

当你最需要的是合格的名称时,避免使用from ... import(可怕的;-)方式来获取全名。一旦你以正确的Pythonic方式做事:

import module

class ReplaceClass(object): ...

module.MyClass = ReplaceClass

通过这种方式,您可以对模块对象进行monkeypatching,这是您需要的,并且当该模块用于其他模块时将会工作。使用from ...表单,您只是不拥有模块对象(查看大多数人使用from ...的明显缺陷的一种方法),所以你是显然更糟; - );

我建议使用from语句的一种方法是从包中导入模块:

from some.package.here import amodule

所以你仍然得到了模块对象,并且将对该模块中的所有名称使用限定名称。

答案 2 :(得分:12)

我只是一个鸡蛋。 。 。 。也许对于非新手来说很明显,但我需要from some.package.module import module成语。

我不得不修改一下GeneralHelpfulClass的一个方法。这失败了:

import some.package.module

class SpeciallyHelpfulClass(some.package.module.GenerallyHelpfulClass): 
    def general_method(self):...

some.package.module.GenerallyHelpfulClass = SpeciallyHelpfulClass

代码已运行,但未使用重载到SpeciallyHelpfulClass上的行为。

这有效:

from some.package import module

class SpeciallyHelpfulClass(module.GenerallyHelpfulClass): 
    def general_method(self):...

module.GenerallyHelpfulClass = SpeciallyHelpfulClass

我推测from ... import成语'正如亚历克斯写的那样得到模块',因为它将被包中的其他模块拾取。进一步推测,较长的虚线引用似乎通过长点引用导入模块进入命名空间,但不会更改其他命名空间使用的模块。因此,对导入模块的更改只会出现在创建它们的名称空间中。就好像有两个相同模块的副本,每个副本都有不同的引用。

答案 3 :(得分:0)

import some_module_name

class MyClass(object): 
     ... #copy/paste source class and update/add your logic

some_module_name.MyClass = MyClass

最好不要在替换时更改类的名称,因为不知何故有人可能使用getattr引用它们 - 这将导致失败,如下所示

getattr(some_module_name, 'MyClass') - >如果你用ReplaceClass替换了MyClass,它将会失败!