Python中的Monkey Patching
Monkey Patching 是Python中令人兴奋的话题。Monkey Patching指的是在运行时修改一个类或模块。简单来说,类或模块的工作可以在运行时改变。让我们通过实际示例理解这个概念。
当我们在一个大型项目上工作时,可能会遇到第三方库不起作用的情况。因此,我们尝试从我们的项目中修订(或更改)它。这个过程被称为Python中的monkey patching。通常情况下,开发人员会避免使用它。然而,它是开发过程的一部分。
在monkey patching中,我们可以重新打开一个类并修改其行为。
我们将学习如何在Python代码中使用monkey patching。
我们知道 Python 是一种动态语言;类是可变的,所以我们可以在需要时修改它们。让我们理解以下示例。
示例
import inspect
class MonkeyPatch:
def __init__(self, n1):
self.n1 = n1
def add(self, other):
return (self.n1 + other)
obj1 = MonkeyPatch(10)
obj1.add(20)
print(inspect.getmembers(obj1, predicate=inspect.ismethod))
输出:
30
[('__init__', >), ('add', >)]
如上面的代码中所示,上面的类中有两个方法 – init和addition。我们调用了add()方法并传入了20作为参数。它返回了30。我们已经定义了 MultiPatch 类,并且有 add() 方法。假设我们将新的方法添加到 MonkeyPatch 类中。
def divide(self, n2):
return(self.n1 - self.n2)
要将divide()方法添加到MonkeyPatch类中,只需将divide函数分配给MonkeyPatch。
MonkeyPatch.divide = divide
新创建的函数将在MonkeyPatch类中可用。让我们看下面的示例。
inspect.getmembers(obj, predicate=inspect.ismethod)
输出:
[('__init__', >), ('subtraction', >)]
函数的动态行为
让我们来看一个示例,以更好地理解动态行为。
示例
# new_monk.py
class A:
def hello(self):
print (" The hello() function is being called")
我们已经创建了一个模块,将在下面的代码中使用,以在运行时更改hello()函数的行为。
import new_monk
def monkey_f(self):
print ("monkey_f() is being called")
# replacing address of "func" with "monkey_f"
new_monk.A.hello = monkey_f
obj = new_monk.A()
# calling function "func" whose address got replaced
# with function "monkey_f()"
obj.hello()
输出:
monkey_f() is being called
内存地址的更改
Python提供了 ctype 模块,可以通过内存地址管理来改变对象的值。因此,不建议这样做,直接的内存操作是不安全且不一致的。可能对一个值起作用,对另一个值却不起作用。
结论
我们已经讨论了如何在Python中实现猴子补丁。但它具有一些缺点,应该小心使用。在应用程序设计中不适合使用,因为它区分了磁盘上的源代码和观察到的行为。开发者在调试时可能会感到困惑。