在Python中是否可以完全从库中对类进行猴子补丁?
我正在尝试向库中添加一些非常基本的功能(即scikit learn)。但是,我不希望直接修改库本身,因为a)即使在我自己的测试中,我也希望能够打开和关闭功能,b)这很可能是不属于库的主代码库的功能 我想做的是对基类(在本例中是sklearn.base.BaseEstimator)进行monkey修补,这样当库中的其他类从该类导入/派生时,它们就会得到我修改过的类。以下是我目前掌握的情况:在Python中是否可以完全从库中对类进行猴子补丁?,python,scikit-learn,Python,Scikit Learn,我正在尝试向库中添加一些非常基本的功能(即scikit learn)。但是,我不希望直接修改库本身,因为a)即使在我自己的测试中,我也希望能够打开和关闭功能,b)这很可能是不属于库的主代码库的功能 我想做的是对基类(在本例中是sklearn.base.BaseEstimator)进行monkey修补,这样当库中的其他类从该类导入/派生时,它们就会得到我修改过的类。以下是我目前掌握的情况: import sklearn from sklearn.base import BaseEstimator
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 patchBaseEnsemble
,您将看到效果。替换类不是很有效,因为其他类已经对原始类进行了子类化,但是您可以这样替换类上的方法:
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
的缺失。我猜我只是假设它会有一个!