我正在使用一段看起来像这样的代码:
# This code is not modifiable
from package import distance as dist
class A:
def calculate(self):
...
# call to dist()
...
我的代码:
from package import A
a = A()
a.calculate()
如您所见,distance()
函数是在代码顶部导入的。班级A
会调用distance()
函数。它是在几个地方,而不仅仅是calculate()
。
我希望班级使用我的自定义距离功能。但是,该类不允许我在构造函数中传递它,我无法修改A
的代码。我该怎么做?这是否可以通过子类化?我尝试了以下,但没有用:
from package import A
class B(A):
def __init__(self):
from mypackage import mydistance as dist
return super().__init__()
b = B()
b.calculate()
答案 0 :(得分:1)
您可以使用mock.patch
功能,如下所示:
distance.py:
def distance():
print('distance called')
mydistance.py:
def mydistance():
print('mydistance called')
a.py:
from distance import distance as dist
class A:
def calculate(self):
dist()
main.py:
from unittest import mock
from a import A
from mydistance import mydistance
class B(A):
def calculate(self):
with mock.patch('a.dist', wraps=mydistance):
super().calculate()
if __name__ == '__main__':
b = B()
b.calculate()
输出是:
mydistance called
根据您的使用情况,您可能希望将with
语句放在其他位置(例如在呼叫站点中)。例如:
if __name__ == '__main__':
b = B()
with mock.patch('a.dist', wraps=mydistance):
for _ in range(0, 100):
b.calculate()
修补会导致一些开销。另一个解决方案(与oetoni建议基本相同)是重新分配属性(记住import a
):
if __name__ == '__main__':
b = B()
old_dist = a.dist
a.dist = mydistance
for _ in range(0, 100):
b.calculate()
a.dist = old_dist
答案 1 :(得分:0)
您可以立即从代码中执行此操作,而无需添加新导入或使用mock.patch或任何第三类B.立即从您引用A的代码中
现在您只需要对代码进行一些小改动,不要只做from package import A
,而是直接导入import baseA
,这样我们就可以控制导入中的所有变量;)因此我们可以。然后我们可以使用它的局部变量名来捕获它并在运行时更改它:D如下:
在导入A
时假设distance()函数<强> distance.py 强>
def distance(something):
return something + 1
然后我假设包含A类的文件名为baseA
<强> baseA.py 强>
# This code is not modifiable
from distance import distance as dist
class A:
def calculate(self):
something = dist(1)
return something
最后你编码包含你运行代码的文件,以及我们想要修改它在baseA中导入的dist()的地方
<强> yourcode.py 强>
import baseA
def newDist(something):
return something + 2
baseA.dist = newDist
a = baseA.A()
something = a.calculate()
print(something)
我成功地设法改变了baseA中dist的行为:)
baseA.dist = newDist
记得不要括号,因为我们将函数作为对象传递,以便将其行为分配给从 distance.py baseA.dist >文件
测试解决方案
答案 2 :(得分:-1)
您可以使用unittest.mock中的patch@
装饰器来完成此操作。