Python如何制作跨模块功能?

Eva*_*van 1 python module global

例如,我希望能够从导入的类中调用全局函数

在文件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()
Run Code Online (Sandbox Code Playgroud)

然后当我在Python Interpreter中测试时

>>> def makenoise():
...    return 'bark'
...
>>> from PetStore import AnimalSound
>>> sound = AnimalSound()
>>> sound.makenoise()
'meow'
Run Code Online (Sandbox Code Playgroud)

我得到'喵'而不是'吠'.我已经尝试过使用python-how-to-make-a-cross-module-variable中提供的解决方案而没有运气.

Ale*_*lli 5

globals()调用返回调用在词法上定位的模块的全局变量; Python中没有内在的"动态范围" - 它是词汇范围的,就像几乎所有现代语言一样.

获得你想要的效果的坚实,正确的方法是明确地传递给AnimalSound它应该用来"制造噪音"的可调用的初始化器:即,类应该是

class AnimalSound(object):
   def __init__(self, makenoise=lambda: 'meow'):
       self.makenoise = makenoise

   def __str__(self):
       return self.makenoise()
Run Code Online (Sandbox Code Playgroud)

和电话应该是

sound = AnimalSound(makenoise)
Run Code Online (Sandbox Code Playgroud)

有一些可行但不太合理的解决方案,例如调用者自己传递globals()(但是不必要地限制了可调用的名称!),甚至(颤抖)通过秘密通道进行通信,就像其他答案拥护者一样(这将是一个潜在的灾难)如果您AnimalSound在两个单独的模块中有两个根据相同原理构建的实例,等等).但是,"明确比隐含更好",干净,安全,公开的沟通会带来清洁,安全,强大的系统架构:我真诚地建议您选择这条路线.