Jun*_*une 5 python monkeypatching
我正在导入其他人制作的库,并且想要更改该库中特定类方法的工作方式,因此我已将该类方法复制到我自己的文件中,并希望在运行时替换它。这对于函数来说似乎工作得很好,但对于类方法来说似乎就不行了。
a.library.package.library_file.py
class LibraryClass(ParentClass):
@classmethod
def get_cost(cls, time):
return int(time * cls.hourly)
Run Code Online (Sandbox Code Playgroud)
我想用这个替换它
class LibraryClass(ParentClass):
@classmethod
def get_cost(cls, time):
return 1234
Run Code Online (Sandbox Code Playgroud)
我尝试只进行正常的替换,这对于常规功能来说效果很好
import a.library.package.library_file
...
a.library.package.library_file.LibraryClass.get_cost = get_cost
Run Code Online (Sandbox Code Playgroud)
但它似乎根本无法正常工作,该方法在错误的时间使用错误的参数调用并导致崩溃。在对 Google、StackOverflow 和 Python 进行一些研究之后,我开始尝试使用模拟类。
from unittest.mock import patch
@patch.object('a.library.package.library_file.LibraryClass', 'get_cost')
def get_cost(cls, time):
return 1234
Run Code Online (Sandbox Code Playgroud)
好消息是它不会崩溃,坏消息是它没有做任何事情,旧代码仍然存在,就像我的代码不存在一样。
我尝试过各种其他方法来做到这一点,例如
import a.library.package.library_file
@patch.object(a.library.package.library_file.LibraryClass, 'get_cost')
...
Run Code Online (Sandbox Code Playgroud)
或者
from a.library.package.library_file import LibraryClass
@patch.object(LibraryClass, 'get_cost')
...
Run Code Online (Sandbox Code Playgroud)
但每次方法都没有碰过。就像我的代码不存在并且使用旧代码一样。
Jun*_*une 10
事实证明,解决方案就像我想象的那样简单。经过一天多的挖掘,网上没有任何帮助,但我在谷歌的第 2 页上发现了一篇来自中国的晦涩的随机帖子,它终于回答了我的问题。链接在这里
这是有效的结果代码
from types import MethodType
from a.library.package.library_file.py import LibraryClass
def get_cost(cls, time):
return 1234
LibraryClass.get_cost = MethodType(get_cost, LibraryClass)
Run Code Online (Sandbox Code Playgroud)
这与替换函数相同,只是您需要将其包装在“MethodType”中,因为您换出的代码与该类有“classmethod”联系,因此新代码需要相同的联系才能工作。
您可以导入原始类并创建自己的继承原始类的类吗?然后,您重新定义要重写的方法,并仅使用自定义类而不是原始类:
from a_library import LibraryClass
class YourClass(LibraryClass):
@classmethod
def get_cost(cls, time):
# redefine the method here
return 1234
cost = YourClass.get_cost(time)
Run Code Online (Sandbox Code Playgroud)
然后只需使用YourClass
而不是库类。它的行为与库类完全相同,但使用您的方法而不是原始方法。
归档时间: |
|
查看次数: |
5031 次 |
最近记录: |