我试图替换在类中定义的函数,以便在不更改实际代码的情况下修改其功能(如内部工作)。

我以前从未做过此事,因此在更换它时会遇到一些问题。

更改代码将使我能够访问我的python库中的软件包,这不是很多选择。

例如,如果模块名为testMOD

class testMOD(object):
def testFunc(self, variable):
var = variable
self.something = var + 12

然后,我将导入testMOD,定义一个类(mytest = testMOD()),并在该类testFunc中访问已定义的函数,并将其更改为已定义的函数。

例如,

from somemodule import testMOD
mytest = testMOD()
def alternativeFunc(self, variable):
var = variable
self.something = var + 1.2
#problem here
mytest.testFunc = alternativeFunc

如您所见,如果我只是用定义的函数手动覆盖(?)类中的函数,它将无法正常工作。

它没有给出任何语法错误,但是,问题是被替换的函数认为'self'是该函数的另一个变量,并说它需要'variable'变量的另一个参数(我想那不是一个好名字)。

我想要做的是使替换函数与被替换函数完全相同,但是要附加代码或进行一些小的修改。但是,"自我"在课堂上几乎没有发挥作用。

是否有一种方法可以正确实现定义的函数来替换导入类的函数?

我建议从最差到最好(IMHO)的4种解决方案,但是当然,这也取决于您的特定限制:

替换实例方法(1):我使用函数是Python中的描述符这一事实,以便可以将AlternativeFunc上的__get__方法用作实例mytest的方法并覆盖mytest的>方法(不覆盖类方法):

class testMOD(object):
def testFunc(self, variable):
var = variable
self.something = var + 12
print('Original:', self.something)
def alternativeFunc1(self, variable):
var = variable
self.something = var + 1.2
print('Alternative1:', self.something)
mytest1 = testMOD()
mytest1.testFunc(10)   # Original: 22
mytest1.testFunc = alternativeFunc1.__get__(mytest1, testMOD)
mytest1.testFunc(10)   # Alternative1: 11.2
mytestX = testMOD()
mytestX.testFunc(10)   # Original: 22

替换实例方法(2):这一次,我使用types.MethodType,它比第一种解决方案更具可读性:

import types
class testMOD(object):
def testFunc(self, variable):
var = variable
self.something = var + 12
print('Original:', self.something)
def alternativeFunc1(self, variable):
var = variable
self.something = var + 1.2
print('Alternative1:', self.something)
mytest1 = testMOD()
mytest1.testFunc(10)   # Original: 22
funcType = types.MethodType
mytest1.testFunc = funcType(alternativeFunc1, mytest1)
mytest1.testFunc(10)   # Alternative1: 11.2
mytestX = testMOD()
mytestX.testFunc(10)   # Original: 22

对类方法执行猴子修补。与第一种方法不同,它更改了该类任何实例的行为:

class testMOD(object):
def testFunc(self, variable):
var = variable
self.something = var + 12
print('Original:', self.something)
def alternativeFunc2(self, variable):
var = variable
self.something = var + 1.2
print('Alternative2:', self.something)
mytest2 = testMOD()
mytest2.testFunc(10)   # Original: 22
testMOD.testFunc = alternativeFunc2
mytest2.testFunc(10)   # Alternative2: 11.2
mytestX = testMOD()
mytestX.testFunc(10)   # Alternative2: 11.2
创建从testMOD继承的类以覆盖该方法:
class testMODNew(testMOD):
def testFunc(self, variable):
var = variable
self.something = var + 1.2
print('Alternative3:', self.something)
mytest3 = testMODNew()
mytest3.testFunc(10) # Alternative3: 11.2
您可以按以下方式猴子修补此方法:
class TestMOD(object):
def testFunc(self, variable):
var = variable
self.something = var + 12
print(f'original {self.something}')
def alternativeFunc(self, variable):
var = variable
self.something = var + 1.2
print(f'alternative {self.something}')
if __name__ == '__main__':
test_original = TestMOD()
test_original.testFunc(12)
TestMOD.testFunc = alternativeFunc
test_alternate = TestMOD()
test_alternate.testFunc(12)
输出:
original 24
alternative 13.2

感谢您的回答! 当我认为自己所做的与您所做的完全相同时,我感到非常困惑,然后我意识到我必须更改实际的类,而不是继承的类变量。

值得一提的是:不必创建新的TestMOD实例。 猴子修补会更改类本身,这也会影响所有现有实例。 调用test_original.testFunc(12)也将具有相同的效果。

在python中检查类继承,以创建自己的自定义类:

from somemodule import TestMOD
class YourCustomClass(TestMOD):
# change the function
def test_func(self, variable):
#
#
your_class = YourCustomClass()
your_class.test_func(x)