0

Is it possible to Monkey Patch an attribute within a Python class? A quick google for "monkey patching python" returns a ton of results about patching methods, but no mention of changing fields within a class.

Patching Methods:

However, like I said, no mention of changing Class attributes/fields.

To give a somewhat contrived example, let's say I have a class which has a multiprocessing queue, and I want to patch it with a threading Queue.Queue.

import threading 
import multiprocessing

class MyClassWithAQueue(object):
        def__init__(self):
                self.q = multiprocessing.Queue()

Is there a way to patch this? Attempting to simply assign it via the class name before construction appears to do nothing.

if __name__ == '__main__':
        MyClassWithAQueue.q = Queue.Queue()
        myclass = MyClassWithAQueue()

        print myclass.q 
            # still shows as a multiprocessing queue
        >>><multiprocessing.queues.Queue object at 0x10064493>

Is there a way to do this?

Community
  • 1
  • 1
Zack Yoshyaro
  • 2,056
  • 6
  • 24
  • 46
  • You must either create instance of the original class and then rewrite the actual value of the field, or monkey patch the class by replacing the constructor. But I don’t recommend using monkey patching at all. There are often much better ways to solve the problem you have. – Palec Feb 08 '14 at 01:32
  • What do you need to monkey patch in the first place? – Lukasz Madon Feb 08 '14 at 01:34

1 Answers1

1

The problem is the order in which the code runs.

__init__ runs on instantiation, and is setting self.q, regardless of what if anything it was before. You can do one of the following:


Change it to a class attribute:

class MyClassWithAQueue(object):
    q = multiprocessing.Queue()
    def __init__(self):
        pass

MyClassWithAQueue.q = Queue.Queue()
myclass = MyClassWithAQueue()
print myclass.q

Or change the instance attribute:

class MyClassWithAQueue(object):
    def __init__(self):
        self.q = multiprocessing.Queue()

myclass = MyClassWithAQueue()
myclass.q = Queue.Queue()
print myclass.q
mhlester
  • 22,781
  • 10
  • 52
  • 75