python - 是否有可能对 Python 库中的类进行完全猴子修补?

标签 python scikit-learn

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

我想做的是对基类(在本例中为 sklearn.base.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.ensemble.base.BaseEnsemble。查看 sklearn/ensemble/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 没有定义 __init__ 方法,因此它的子级不会调用 super.__init__。但是,如果您对 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()

这确实打印了

关于python - 是否有可能对 Python 库中的类进行完全猴子修补?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37569879/

相关文章:

python - 使用散列从数据框中删除列

javascript - Django 模块缩短生产中的 css 类

python - 属性错误: 'CalibratedClassifierCV' object has no attribute 'coef_'

python - 如何将数据集拆分为训练集和验证集以保持类之间的比率?

python - 将 PMML 模型导入 Python (Scikit-learn)

python - Python list.extend() 是 Order Presserving 吗?

python - 将 bash 脚本转换为 python 的问题

scikit-learn - 特征选择和预测

linux - 为什么 sklearn 中的核心事件在时间 RFECV/LogisticRegression 后减少

python - 在python中将数据帧打印到.csv。 TypeError :must be convertible to a buffer