Un caso de uso típico es: enriquecer un (enorme) módulo existente con algunos (pocos) atributos dinámicos, sin convertir todo el material del módulo en un diseño de clase. Desafortunadamente un parche de clase de módulo más simple como sys.modules[__name__].__class__ = MyPropertyModule
falla con TypeError: __class__ assignment: only for heap types
. Entonces la creación del módulo necesita ser reconectada.
Este enfoque hace sin Python ganchos de importación, sólo por tener algún prólogo en la parte superior del código del módulo:
# propertymodule.py
""" Module property example """
if '__orgmod__' not in globals():
# constant prolog for having module properties/supports reload()
print "PropertyModule stub execution", __name__
import sys, types
class PropertyModule(types.ModuleType):
def __str__(self):
return "<PropertyModule %r from %r>" % (self.__name__, self.__file__)
modnew = PropertyModule(__name__, __doc__)
modnew.__modclass__ = PropertyModule
modnew.__file__ = __file__
modnew.__orgmod__ = sys.modules[__name__]
sys.modules[__name__] = modnew
exec sys._getframe().f_code in modnew.__dict__
else:
# normal module code (usually vast) ..
print "regular module execution"
a = 7
def get_dynval(module):
return "property function returns %s in module %r" % (a * 4, module.__name__)
__modclass__.dynval = property(get_dynval)
Uso:
>>> import propertymodule
PropertyModule stub execution propertymodule
regular module execution
>>> propertymodule.dynval
"property function returns 28 in module 'propertymodule'"
>>> reload(propertymodule) # AFTER EDITS
regular module execution
<module 'propertymodule' from 'propertymodule.pyc'>
>>> propertymodule.dynval
"property function returns 36 in module 'propertymodule'"
Nota: Algo así como from propertymodule import dynval
producirá una congelada copia por supuesto - correspondiente a dynval = someobject.dynval
¿Qué hay de malo con solo llamar a una función? –
quiero hacer menos tipeo para hacer ciertas cosas que se hacen mucho. –