0

I have three modules:

in_mod.py

class IN(object):
    def __init__(self):
        print("i am the original IN")

module1.py

from in_mod import IN
class C(object):
    def __init__(self):
        cl = IN()

and module2.py

from module1 import C
class IN2(object):
    def __init__(self):
        print("I am the new IN")

C()

import in_mod
in_mod.IN = IN2
C()

import module1
module1.IN = IN2
C()

I get the desired behaviour of monkey-patching out the IN class and replacing it with the IN2 class when I use module1.IN = IN2.

I would like to understand what the underlying difference between in_mod.IN = IN2 and module1.IN = IN2 is in this context.

I am referencing a related post.

Community
  • 1
  • 1
Pete
  • 137
  • 1
  • 7
  • 2
    `IN = IN2` *shadows* the imported version within `module2`, but doesn't actually alter `module1` at all. Any functionality inside `module1` still sees the previous version. What are you actually trying to patch, and why (e.g. for testing)? – jonrsharpe Mar 07 '16 at 11:51
  • In the first example, `C2` inherits from `module1.c`, but in the second, you import `C2` from `module1`, but inherit from `C` -- I'm not sure why. Could you say more about what "the expected behavior" is for you, and why? – senderle Mar 07 '16 at 11:56
  • Yes this is for testing. I am trying to mock out IN with IN2. The module I am trying to test imports IN using `from .. import` and I can't change it. – Pete Mar 07 '16 at 22:18

1 Answers1

3

from module import IN creates a local variable that references module.IN; module.IN and IN are two separate references to the same class. IN = IN2 changes the local reference, but module.IN (which is used by module.C) continues to reference the same class.


UPDATE

In your edit, module1.IN is a global variable in the module1 namespace that initially refers to a class in in_mod, but is distinct from the global in_mod.IN in the module namespace. Changing its value doesn't affect in_mod at all. There's no way to directly access in_mod's namespace via module1, because you don't import the entire module, just one value from the module.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • ok thanks. I think this is the understanding that I needed. The next question is how I can change the reference used by module.C – Pete Mar 07 '16 at 22:27
  • That's what you did in your first example: assign directly to `module.IN`. – chepner Mar 07 '16 at 23:03
  • Ok, i've refactored the code in the question quite alot to hopefully make it clearer and closer to what I have in my application. I think I have something that works now, but I'm still not sure I fully understand why. Can you take a look? Thanks – Pete Mar 07 '16 at 23:45
  • Ok thanks. This makes sense to me know and works for my application. [This SO post](http://stackoverflow.com/questions/3765222/monkey-patch-python-class) also provides a good explanation of this. – Pete Mar 08 '16 at 06:02