在Python中是否可以完全从库中对类进行猴子补丁?

在Python中是否可以完全从库中对类进行猴子补丁?,python,scikit-learn,Python,Scikit Learn,我正在尝试向库中添加一些非常基本的功能(即scikit learn)。但是,我不希望直接修改库本身,因为a)即使在我自己的测试中,我也希望能够打开和关闭功能,b)这很可能是不属于库的主代码库的功能 我想做的是对基类(在本例中是sklearn.base.BaseEstimator)进行monkey修补,这样当库中的其他类从该类导入/派生时,它们就会得到我修改过的类。以下是我目前掌握的情况: import sklearn from sklearn.base import BaseEstimator

我正在尝试向库中添加一些非常基本的功能(即scikit learn)。但是,我不希望直接修改库本身,因为a)即使在我自己的测试中,我也希望能够打开和关闭功能,b)这很可能是不属于库的主代码库的功能

我想做的是对基类(在本例中是sklearn.base.BaseEstimator)进行monkey修补,这样当库中的其他类从该类导入/派生时,它们就会得到我修改过的类。以下是我目前掌握的情况:

import sklearn
from sklearn.base import BaseEstimator
from sklearn import base

class InstrumentedEstimator(sklearn.base.BaseEstimator):
    def __init__(self, *args, **kwargs):
        print 'called'
        super(InstrumentedEstimator, self).__init__(*args, **kwargs)

sklearn.base.BaseEstimator = InstrumentedEstimator
base.BaseEstimator = InstrumentedEstimator
BaseEstimator = InstrumentedEstimator

from sklearn.ensemble import RandomForestClassifier
RandomForestClassifier()
这不起作用-即,
RandomForestClassifier()
不打印调用的
。我怀疑这里的主要原因是,当查看
RandomForestClassifier
的层次结构时,从BaseEstimator派生的最终父类是
sklearn.employee.base.baseemploy
。查看sklearn/emose/base.py,可以看到以下内容:

from ..base import BaseEstimator
甚至可以用Python对这种风格的导入进行修补吗?更重要的是,是否有可能(显然是在程序的上下文中)对该类的所有实例进行修补,而不管它们在何处以及如何导入

理想情况下,最终游戏将是这样的:

import my_module
from sklearn.(anything) import SomeEstimator

SomeEstimator()  # this runs my code in addition to SomeEstimator's code
...

问题是
BaseEstimator
没有定义
\uuuuu init\uuuuu
方法,因此它的子级不调用
super.\uuuuu init\uuuu
。但是,如果您使用monkey patch
BaseEnsemble
,您将看到效果。替换类不是很有效,因为其他类已经对原始类进行了子类化,但是您可以这样替换类上的方法:

from sklearn.ensemble import BaseEnsemble, RandomForestClassifier

old_init = BaseEnsemble.__init__

def new_init(*args, **kwargs):
    print 'called'
    old_init(*args, **kwargs)

BaseEnsemble.__init__ = new_init

RandomForestClassifier()

这确实打印了名为

Doh!我不敢相信我没有注意到
\uuuuu init\uuuuu
的缺失。我猜我只是假设它会有一个!