I want to be able to call a global function from an imported class, for example
In file PetStore.py
class AnimalSound(object):
def __init__(self):
if 'makenoise' in globals():
self.makenoise = globals()['makenoise']
else:
self.makenoise = lambda: 'meow'
def __str__(self):
return self.makenoise()
Then when I test in the Python Interpreter
>>> def makenoise():
... return 'bark'
...
>>> from PetStore import AnimalSound
>>> sound = AnimalSound()
>>> sound.makenoise()
'meow'
I get a ‘meow’ instead of ‘bark’. I have tried using the solutions provided in python-how-to-make-a-cross-module-variable with no luck.
The
globals()call returns the globals of the module in which the call is lexically located; there is no intrinsic “dynamic scoping” in Python — it’s lexically scoped, like just about every modern language.The solid, proper way to obtain the effect you desire is to explicitly pass to the initializer of
AnimalSoundthe callable it’s supposed to use to “make noise”: i.e., the class should beand the call should be
There are practicable but less-sound solutions, such as the caller passing its own
globals()(but that needlessly constrains the name of the callable!), or even (shudder) communicating via covert channels like the other answer advocates (that would be a potential disaster if you had two instantiations ofAnimalSoundbuilt according to the same principle in two separate modules, etc, etc). But, “explicit is better than implicit”, and clean, safe, overt communication leads to clean, safe, robust system architectures: I earnestly recommend you choose this route.