Здесь есть две основные проблемы:
__xxx__
методы ищутся только в классе
TypeError: can't set attributes of built-in/extension type 'module'
(1) означает, что любое решение должно также отслеживать, какой модуль проверяется, в противном случае каждый модуль будет иметь поведение замены экземпляра; и (2) означает, что (1) даже невозможно ... по крайней мере, напрямую.
К счастью, sys.modules не разборчивы в отношении того, что происходит, поэтому обертка будет работать, но только для доступа к модулю (т. Е. import somemodule; somemodule.salutation('world')
; для доступа с одним и тем же модулем вам в значительной степени придется вытащить методы из класса подстановки и добавьте их в globals()
eiher с помощью пользовательского метода в классе (мне нравится использовать .export()
) или с помощью универсальной функции (например, те, которые уже перечислены в качестве ответов). Следует иметь в виду одну вещь: если оболочка создает каждый раз новый экземпляр, а глобальное решение - нет, в конечном итоге вы ведете себя слегка по-разному. О, и вы не можете использовать оба одновременно - это одно или другое.
Обновление
С Гвидо ван Россум :
На самом деле есть хак, который иногда используется и рекомендуется:
Модуль может определить класс с желаемой функциональностью, а затем в
конец, замените себя в sys.modules экземпляром этого класса
(или с классом, если вы настаиваете, но это, как правило, менее полезно).
E.g.:
# 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__
по мере необходимости.
Обратите внимание, что если вы используете эту функцию, все остальное в модуле, такое как глобальные переменные, другие функции и т. Д., Будет потеряно при назначении sys.modules
, поэтому убедитесь, что все необходимое находится внутри класса замены.