Python教程-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 和 add。我们调用了 add() 方法并传递了20作为参数。它返回了30。我们定义了 MonkeyPatch 类,并在其中定义了 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提供了 ctypes 模块,用于通过内存地址管理更改对象的值。因此,不建议进行直接内存操作,这是不安全的并且不一致。可能对一个值有效,而对另一个值无效。
结论
我们已经讨论了如何在Python中实现Monkey Patching。但是它具有一些缺点,应谨慎使用。在应用程序设计中不建议使用它,因为它会使源代码在磁盘上和观察的行为之间产生差异。在调试时,开发者可能会感到困惑。