Ответ Кристофа Боддекера кажется наилучшим способом создания вызываемого модуля, но, как говорит комментарий , он работает только в Python 3.5 и выше.
Преимущество заключается в том, что вы можете написать свой модуль как обычно и просто добавить переназначение класса в самом конце, т.е.
# coolmodule.py
import stuff
var = 33
class MyClass:
...
def function(x, y):
...
class CoolModule(types.ModuleType):
def __call__(self):
return 42
sys.modules[__name__].__class__ = CoolModule
и все работает, включая все ожидаемые атрибуты модуля, такие как __file__
, которые определены. (Это потому, что вы на самом деле вообще не изменяете объект модуля, полученный в результате импорта, просто «приводите» его к подклассу с помощью метода __call__
, что в точности соответствует нашему желанию.)
Чтобы это работало аналогично в версиях Python ниже 3.5, вы можете приспособить ответ Алекса Мартелли , чтобы сделать ваш новый класс подклассом ModuleType, и скопировать все атрибуты модуля в ваш новый экземпляр модуля:
#(all your module stuff here)
class CoolModule(types.ModuleType):
def __init__(self):
types.ModuleType.__init__(self, __name__)
# or super().__init__(__name__) for Python 3
self.__dict__.update(sys.modules[__name__].__dict__)
def __call__(self):
return 42
sys.modules[__name__] = CoolModule()
Теперь определены __file__
, __name__
и другие атрибуты модуля (которые отсутствуют, если просто следуют за ответом Алекса), и ваш импортированный объект модуля все еще «является» модулем.