How does one monkey patch a function in python?

前端 未结 5 1682
没有蜡笔的小新
没有蜡笔的小新 2020-11-29 19:58

I\'m having trouble replacing a function from a different module with another function and it\'s driving me crazy.

Let\'s say I have a module bar.py that looks like

5条回答
  •  抹茶落季
    2020-11-29 20:08

    In the first snippet, you make bar.do_something_expensive refer to the function object that a_package.baz.do_something_expensive refers to at that moment. To really "monkeypatch" that you would need to change the function itself (you are only changing what names refer to); this is possible, but you do not actually want to do that.

    In your attempts to change the behavior of a_function, you have done two things:

    1. In the first attempt, you make do_something_expensive a global name in your module. However, you are calling a_function, which does not look in your module to resolve names, so it still refers to the same function.

    2. In the second example you change what a_package.baz.do_something_expensive refers to, but bar.do_something_expensive is not magically tied to it. That name still refers to the function object it looked up when it was initilized.

    The simplest but far-from-ideal approach would be to change bar.py to say

    import a_package.baz
    
    def a_function():
        print a_package.baz.do_something_expensive()
    

    The right solution is probably one of two things:

    • Redefine a_function to take a function as an argument and call that, rather than trying to sneak in and change what function it is hard coded to refer to, or
    • Store the function to be used in an instance of a class; this is how we do mutable state in Python.

    Using globals (this is what changing module-level stuff from other modules is) is a bad thing that leads to unmaintainable, confusing, untestestable, unscalable code the flow of which is difficult to track.

提交回复
热议问题