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__(sel开发者_如何学运维f):
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 AnimalSound
the callable it's supposed to use to "make noise": i.e., the class should be
class AnimalSound(object):
def __init__(self, makenoise=lambda: 'meow'):
self.makenoise = makenoise
def __str__(self):
return self.makenoise()
and the call should be
sound = AnimalSound(makenoise)
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 of AnimalSound
built 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.
"Global" scope in Python is Module scope.
import PetStore
PetStore.makenoise = makenoise
精彩评论