Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 什么是猴子修补术?_Python_Terminology_Monkeypatching - Fatal编程技术网

Python 什么是猴子修补术?

Python 什么是猴子修补术?,python,terminology,monkeypatching,Python,Terminology,Monkeypatching,我试图理解,什么是猴子补丁或猴子补丁 这是否类似于方法/运算符重载或委派 它与这些东西有什么共同之处吗?根据: 在Python中,术语monkey patch仅用于 指的是对对象的动态修改 运行时的类或模块,受激励 通过修补现有的 第三方代码作为解决方案 不起作用的bug或特性 你想要的 不,它不像那些东西。它只是在运行时动态替换属性 例如,考虑一个类,该类具有一个方法:代码> GETyDATA < /COD>。此方法执行外部查找(例如,在数据库或web API上),类中的其他各种方法调用它。但

我试图理解,什么是猴子补丁或猴子补丁

这是否类似于方法/运算符重载或委派

它与这些东西有什么共同之处吗?

根据:

在Python中,术语monkey patch仅用于 指的是对对象的动态修改 运行时的类或模块,受激励 通过修补现有的 第三方代码作为解决方案 不起作用的bug或特性 你想要的


不,它不像那些东西。它只是在运行时动态替换属性

例如,考虑一个类,该类具有一个方法:代码> GETyDATA < /COD>。此方法执行外部查找(例如,在数据库或web API上),类中的其他各种方法调用它。但是,在单元测试中,您不希望依赖于外部数据源,因此可以使用返回一些固定数据的存根动态替换

get\u data
方法

因为Python类是可变的,而方法只是类的属性,所以您可以随心所欲地执行此操作——事实上,您甚至可以用完全相同的方式替换模块中的类和函数

但是,正如一位专家所指出的,在修补monkeypatching时要小心:

  • 如果除了您的测试逻辑之外,还有其他任何东西也调用了
    get_data
    ,那么它也会调用您的monkey patched replacement,而不是原始的,这可能是好的,也可能是坏的。小心点

  • 如果在替换时存在同样指向
    get_data
    函数的变量或属性,则此别名不会改变其含义,并将继续指向原始
    get_data
    。(为什么?Python只是将类中的名称
    get_data
    重新绑定到其他函数对象;其他名称绑定根本不受影响。)


  • 第一:猴子补丁是一种邪恶的黑客(在我看来)

    它通常用于用自定义实现替换模块或类级别的方法


    最常见的用例是在无法替换原始代码时,为模块或类中的错误添加一个变通方法。在这种情况下,您可以使用自己的模块/包中的实现通过monkey patching替换“错误”的代码。

    monkey patching只能在动态语言中完成,python就是一个很好的例子。例如,在运行时更改方法而不是更新对象定义;类似地,在运行时添加属性(无论是方法还是变量)被认为是猴子补丁。这些通常是在使用没有源代码的模块时完成的,因此对象定义不容易更改

    这被认为是不好的,因为这意味着对象的定义不能完全或准确地描述其实际行为

    MonkeyPatch是一段Python代码,可以扩展或修改 运行时的其他代码(通常在启动时)

    一个简单的例子如下所示:

    from SomeOtherProduct.SomeModule import SomeClass
    
    def speak(self):
        return "ook ook eee eee eee!"
    
    SomeClass.speak = speak
    
    来源:Zope wiki上的页面

    什么是猴子补丁? 简单地说,monkey patching就是在程序运行时对模块或类进行更改

    使用中的示例 熊猫文档中有一个猴子修补的例子:

    import pandas as pd
    def just_foo_cols(self):
        """Get a list of column names containing the string 'foo'
    
        """
        return [x for x in self.columns if 'foo' in x]
    
    pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
    df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
    df.just_foo_cols()
    del pd.DataFrame.just_foo_cols # you can also remove the new method
    
    要解决此问题,首先我们导入模块:

    import pandas as pd
    
    接下来,我们创建一个方法定义,它存在于任何类定义的范围之外(因为函数和未绑定方法之间的区别是毫无意义的,Python 3取消了未绑定方法):

    接下来,我们只需将该方法附加到要在其上使用的类:

    pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
    
    然后我们可以在类的实例上使用该方法,并在完成后删除该方法:

    df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
    df.just_foo_cols()
    del pd.DataFrame.just_foo_cols # you can also remove the new method
    
    名称损坏的警告 如果您使用名称mangling(在属性前面加上双下划线,这会改变名称,我不推荐这样做),如果您这样做,您必须手动命名mangle。因为我不推荐名称损坏,所以我不会在这里演示

    测试示例 例如,我们如何在测试中使用这些知识

    假设我们需要模拟对外部数据源的数据检索调用,从而导致错误,因为我们希望在这种情况下确保行为正确。我们可以对数据结构进行修补以确保这种行为。(因此使用Daniel Roseman建议的类似方法名称:)

    当我们测试依赖于此方法的行为时,会引发错误,如果正确实现,我们将在测试结果中得到该行为

    仅执行上述操作将改变进程生命周期内的
    结构
    对象,因此您希望在单元测试中使用设置和拆卸来避免这样做,例如:

    def setUp(self):
        # retain a pointer to the actual real method:
        self.real_get_data = datasource.Structure.get_data
        # monkey patch it:
        datasource.Structure.get_data = get_data
    
    def tearDown(self):
        # give the real method back to the Structure object:
        datasource.Structure.get_data = self.real_get_data
    

    (虽然上面的操作很好,但是使用
    mock
    库来修补代码可能是一个更好的主意。
    mock
    patch
    decorator比上面的操作更不容易出错,这将需要更多的代码行,从而有更多的机会引入错误。我还没有在
    mock但我想它也以类似的方式使用monkey patching。)

    monkey patching是在运行时重新打开类中现有的类或方法,并更改行为,应该谨慎使用,或者只在真正需要时才使用

    由于Python是一种动态编程语言,类是可变的,因此您可以重新打开它们,修改甚至替换它们

    什么是monkey patching?monkey patching是一种用于在运行时动态更新代码行为的技术

    为什么要使用猴子补丁?它允许我们在运行时修改或扩展库、模块、类或方法的行为,而无需 实际修改源代码

    结论猴子修补术是一种很酷的技术,现在我们已经学会了如何进行修补
    import datasource
    
    def get_data(self):
        '''monkey patch datasource.Structure with this to simulate error'''
        raise datasource.DataRetrievalError
    
    datasource.Structure.get_data = get_data
    
    def setUp(self):
        # retain a pointer to the actual real method:
        self.real_get_data = datasource.Structure.get_data
        # monkey patch it:
        datasource.Structure.get_data = get_data
    
    def tearDown(self):
        # give the real method back to the Structure object:
        datasource.Structure.get_data = self.real_get_data