Здесь вы столкнетесь с двумя основными проблемами:
__xxx__
методы ищутся только в классе
TypeError: can't set attributes of built-in/extension type 'module'
(1) означает, что любое решение должно также отслеживать, какой модуль исследуется, иначе каждый модуль будет иметь поведение подстановки экземпляра; и (2) означает, что (1) даже невозможно ... по крайней мере, не напрямую.
К счастью, sys.modules не разборчивы в том, что там происходит, поэтому оболочка будет работать, но только для доступа к модулю (т. Е. Для доступа import somemodule; somemodule.salutation('world')
к тому же модулю вам в значительной степени придется выдернуть методы из класса подстановки и добавить их в globals()
любой другой с помощью пользовательский метод в классе (мне нравится использовать .export()
) или с общей функцией (например, те, которые уже указаны в качестве ответов). Одна вещь, о которой следует помнить: если оболочка создает новый экземпляр каждый раз, а глобальное решение - нет, вы в конечном итоге ведете слегка различающееся поведение О, и вы не можете использовать оба одновременно - это одно или другое.
Обновить
От Гвидо ван Россума :
На самом деле есть хак, который иногда используется и рекомендуется: модуль может определить класс с желаемой функциональностью, а затем в конце заменить себя в sys.modules экземпляром этого класса (или классом, если вы настаиваете , но это обычно менее полезно). Например:
# module foo.py
import sys
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
sys.modules[__name__] = Foo()
Это работает, потому что механизм импорта активно активирует этот взлом и на своем последнем шаге извлекает фактический модуль из sys.modules после его загрузки. (Это не случайно. Взлом был предложен давно, и мы решили, что нам достаточно, чтобы поддержать его в импортном оборудовании.)
Итак, установленный способ добиться того, что вы хотите, - это создать один класс в вашем модуле и в качестве последнего действия модуля заменить sys.modules[__name__]
его экземпляром вашего класса - и теперь вы можете играть с __getattr__
/ __setattr__
/ по __getattribute__
мере необходимости.
Примечание 1. Если вы используете эту функцию, тогда все остальное в модуле, например глобальные объекты, другие функции и т. Д., Будет потеряно при выполнении sys.modules
назначения - поэтому убедитесь, что все необходимое находится внутри класса замены.
Примечание 2 : Для поддержки from module import *
вы должны __all__
определить в классе; например:
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
__all__ = list(set(vars().keys()) - {'__module__', '__qualname__'})
В зависимости от вашей версии Python могут быть другие имена, которые следует опустить __all__
. set()
Может быть опущена , если совместимость Python 2 не требуется.