Redefining a called function from an imported module

danwald10 :

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.

JL Peyret :

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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=31646&siteId=1