有没有可能在Python中从库中完全monkeypatch一个类?

2024-10-01 17:38:42 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我想做的是对基类进行monkey补丁(在本例中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()不打印called。我怀疑这里的主要原因是当查看RandomForestClassifier的层次结构时,从BaseEstimator派生的最终父类是sklearn.ensemble.base.BaseEnsemble。看sklearn/Ensement/基准.py,可以看到以下内容:

^{2}$

甚至可以用Python对这种风格的导入进行monkey补丁吗?更重要的是,有没有可能(显然在程序的上下文中)对这个类的所有实例进行monkey-patch,而不管它们是在何处以何种方式导入的?在

理想情况下,最后的游戏应该是这样的:

import my_module
from sklearn.(anything) import SomeEstimator

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

Tags: fromimportself功能baseinit情况args
1条回答
网友
1楼 · 发布于 2024-10-01 17:38:42

问题是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()

这确实打印called。在

相关问题 更多 >

    热门问题