Python 如何实现跨模块函数?

1 投票
2 回答
1157 浏览
提问于 2025-04-15 22:58

我想从一个导入的类中调用一个全局函数,比如说

在文件 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()

然后当我在 Python 解释器中测试时

>>> def makenoise():
...    return 'bark'
...
>>> from PetStore import AnimalSound
>>> sound = AnimalSound()
>>> sound.makenoise()
'meow'

我得到的是 'meow' 而不是 'bark'。我试过在 python-how-to-make-a-cross-module-variable 中提供的解决方案,但没有成功。

2 个回答

2

在Python中,“全局”范围其实指的是模块范围。

import PetStore

PetStore.makenoise = makenoise
5

globals()这个函数会返回调用它的模块中的全局变量。Python没有所谓的“动态作用域”,它是基于代码位置的作用域,这和大多数现代编程语言是一样的。

想要实现你想要的效果,最好的方法是明确地把一个可以调用的函数传给AnimalSound的初始化器,也就是说,类应该是

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

   def __str__(self):
       return self.makenoise()

而调用应该是

sound = AnimalSound(makenoise)

还有一些可行但不太好的解决方案,比如调用者传自己的globals()(但这样会限制可调用函数的名称!),甚至(让人不安)通过隐秘的方式进行沟通,就像其他答案提到的那样(如果你在两个不同的模块中根据同样的原则创建了两个AnimalSound的实例,那可能会出大问题)。不过,“明确比隐含更好”,清晰、安全、直接的沟通会导致更干净、更安全、更稳健的系统架构:我真心建议你选择这个方法。

撰写回答