Derivacion de tipos, interceptar operaciones
Chema Cortes
py en ch3m4.org
Mar Mar 18 01:20:12 CET 2008
El Monday 17 March 2008 22:03:18 Oswaldo Hernández escribió:
> Muy, muy, muy interesante, aunque no es lo mismo, se parece bastante a mi
> proyecto. Lo revisare con detenimiento.
> Sobre los slots habia visto algo, pero lo volveré a revisar.
Lo de los slots no tiene demasiada importancia. Tan sólo saber que está ahí
por si quieres un control más fino.
Algunos consejos del código que has puesto:
> Mi necesidad es filtrar las instancias antes de que se realice cualquier
> tipo de operacion con ellas, y en ciertos casos impedir la operacion
> lanzando un ValueError.
>
> Un resumen de lo que he hecho he hecho es lo siguiente:
>
> 1.- Definicion de las clases con un metodo __new__ comun
>
> # esta funcion es llamada en el new de las bases para verificar valores y
> creacion de instancia def _Super_New_(cls, *args):
> # verificacion de rango
> if cls.Rango and args[0] < cls.Rango[0] or args[0] > cls.Rango[1]:
Los rangos, en python, quedan más elegantes así:
... and cls.Rango[1]<args[0]<cls.Rango[0]
> raise ValueError
> ...otros chequeos y adaptaciones ...
>
> return = cls.__base__.__new__(cls, *args)
>
> # Clases principales
> class c_int(int):
> Valido = True # en ciertos casos me interesa no dar error
> # y marcar la instancia como 'No Valida'
> Rango = None
> def __new__(cls, *args):
> return _Super_new_(cls, *args)
Mejor así:
__new__=_Super_new_
Da más a entender que "_Super_new_" es un descriptor.
> class c_date(datetime.date):
> Valido = True
> Rango = None
> def __new__(cls, *args):
> return _Super_new_(cls, *args)
Evidentemente, necesitas "metaclases":
class M(type):
def __new__(meta,name,base,dic):
dic.update({
"Valido":True,
"Rango":None,
"__new__":_Super_new_,
})
return type.__new__(meta,name,base,dic)
class c_int(int):
__metaclass__=M
class c_date(datetime.date):
__metaclass__=M
De manera similar, se pueden definir todos los wrappers a los métodos
estáticos dentro de la metaclase:
Operadores = ("__add__", "__sub__", ....)
def __wrapper(op):
def __supermethod(self, *args,**kwds):
if not self.Valido:
raise ValueError
if hasattr(args[0], "Valido") and not args[0].Valido:
raise ValueError
return getattr(self.__base__, op)(self, *args, **kwds)
return __supermethod
class M(type):
def __new__(meta,name,base,dic):
dic.update({
"Valido":True,
"Rango":None,
"__new__":_Super_new_,
})
for op in Operadores:
dic[op]=__wrapper(op)
return type.__new__(meta,name,base,dic)
Lo he hecho muy rápido, así que mejor será que revises y lo ajustes a lo que
quieres hacer. Creo que por aquí tienes por donde trabajar.
------------ próxima parte ------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part.
URL: <http://mail.python.org/pipermail/python-es/attachments/20080318/b4e78cb2/attachment.pgp>
------------ próxima parte ------------
_______________________________________________
Lista de correo Python-es
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes
Más información sobre la lista de distribución Python-es