Une réponse courte : utilisez proxy_tools
El proxy_tools
Le paquet tente de fournir @module_property
fonctionnalité.
Il s'installe avec
pip install proxy_tools
En utilisant une légère modification de l'exemple de @Marein, en the_module.py
nous mettons
from proxy_tools import module_property
@module_property
def thing():
print(". ", end='') # Prints ". " on each invocation
return 'hello'
Maintenant, à partir d'un autre script, je peux faire
import the_module
print(the_module.thing)
# . hello
Comportement inattendu
Cette solution n'est pas sans inconvénient. A savoir , the_module.thing
es pas une chaîne ! Il s'agit d'un proxy_tools.Proxy
dont les méthodes spéciales ont été surchargées afin qu'il imite une chaîne de caractères. Voici quelques tests de base qui illustrent ce point :
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']
En interne, la fonction originale est stockée dans the_module.thing._Proxy__local
:
print(res._Proxy__local)
# <function thing at 0x7f729c3bf680>
Autres réflexions
Honnêtement, je ne comprends pas pourquoi les modules n'ont pas cette fonctionnalité intégrée. Je pense que le nœud du problème est que the_module
est une instance de la types.ModuleType
classe. Définir une "propriété de module" revient à définir une propriété sur une classe instance de cette classe, plutôt que sur le types.ModuleType
la classe elle-même. Pour plus de détails, voir cette réponse .
Nous pouvons en fait mettre en œuvre des propriétés sur types.ModuleType
comme suit, bien que les résultats ne soient pas excellents. Nous ne pouvons pas modifier directement les types intégrés, mais nous pouvons malédiction les :
# 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__}'))
Cela nous donne une propriété qui existe sur tous les modules. C'est un peu lourd, car nous cassons le comportement de réglage dans tous les modules :
import sys
print(sys.thing2)
# hi from sys
sys.thing2 = 5
# AttributeError: can't set attribute
3 votes
Ver
__getattr__
sur un module pour une solution plus moderne.