So for example I have mod1.py:
def foo():
bar()
def bar():
print("This is bar in mod1")
And a mod2.py:
from mod1 import *
def bar():
print("This is bar in mod2")
And then mod3.py:
import mod1
import mod2
mod1.foo()
mod2.foo()
After running mod3.py, I get the same output: "This is bar in mod1", even though I redefined it in mod2.py.
As far as I understand, when I call foo in mod2, it looks it up in mod1 since I imported it and didn't redefine it.
Is there a way I can make foo look for bar in mod2 instead of mod1?
Ofc without copying foo to mod2 or touching foo or bar in mod1 and be able to call them both in mod3, distinguished by their namespaces as in the mod3.py example.
Not too difficult, just pass in the bar
explictly.
Which upon closer reading of the question is off limits as mod1.py can't be touched. Oh well, leaving it still.
mod1.py
def bar():
print("This is bar in mod1")
def foo(bar=bar):
bar()
mod2.py is unchanged
mod3.py
import mod1
import mod2
mod1.foo()
mod2.foo()
mod2.foo(mod2.bar)
output:
This is bar in mod1
This is bar in mod1
This is bar in mod2
update: without touching mod1's source:
Monkeypatching, more or less. Thread safety? Probably not.
import mod1
import mod2
mod1.foo()
ori_bar = mod1.bar
# I think this would be a good place for a context manager rather than
# finally which needs adjustments to handle exceptions
try:
mod1.bar = mod2.bar
mod2.foo()
finally:
mod1.bar = ori_bar
mod1.foo()
output:
This is bar in mod1
This is bar in mod2
This is bar in mod1
Terminology-wise, would the original foo
implementation be considered as a closure? Because I believe this specific behavior has been around for a long time in Python.