Коротка відповідь: використовуйте proxy_tools
proxy_tools
Пакет намагається забезпечити @module_property
функціональні можливості .
Він встановлюється за допомогою
pip install proxy_tools
Використовуючи невелику модифікацію прикладу @ Marein, the_module.py
ми поклали
from proxy_tools import module_property
@module_property
def thing():
print(". ", end='') # Prints ". " on each invocation
return 'hello'
Тепер з іншого сценарію я можу це зробити
import the_module
print(the_module.thing)
# . hello
Несподівана поведінка
Це рішення не позбавлене застережень. А саме, the_module.thing
це не струна ! Це proxy_tools.Proxy
об’єкт, спеціальні методи якого були замінені таким чином, що він імітує рядок. Ось декілька основних тестів, які ілюструють суть:
res = the_module.thing
# [No output!!! Evaluation doesn't occur yet.]
print(type(res))
# <class 'proxy_tools.Proxy'>
print(isinstance(res, str))
# False
print(res)
# . hello
print(res + " there")
# . hello there
print(isinstance(res + "", str))
# . True
print(res.split('e'))
# . ['h', 'llo']
Внутрішньо оригінальна функція зберігається для the_module.thing._Proxy__local
:
print(res._Proxy__local)
# <function thing at 0x7f729c3bf680>
Подальші думки
Чесно кажучи, мене бентежить питання, чому модулі не мають цієї вбудованої функції. Я думаю, суть справи в тому, що the_module
це екземпляр types.ModuleType
класу. Встановлення "властивості модуля" означає встановлення властивості для екземпляра цього класу, а не для самого types.ModuleType
класу. Докладніше див. У цій відповіді .
Ми можемо реалізувати властивості types.ModuleType
наступним чином, хоча результати не є чудовими. Ми не можемо безпосередньо змінювати вбудовані типи, але можемо їх проклинати :
# python -m pip install forbiddenfruit
from forbiddenfruit import curse
from types import ModuleType
# curse has the same signature as setattr.
curse(ModuleType, "thing2", property(lambda module: f'hi from {module.__name__}'))
Це дає нам властивість, яка існує над усіма модулями. Це трохи громіздко, оскільки ми порушуємо поведінку налаштування для всіх модулів:
import sys
print(sys.thing2)
# hi from sys
sys.thing2 = 5
# AttributeError: can't set attribute
__getattr__
модуль для більш сучасного рішення.