Tipo de dato Money

Chema Cortés py en ch3m4.org
Sab Oct 18 03:44:42 CEST 2003


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

El Jueves, 16 de Octubre de 2003 19:57, Batista, Facundo escribió:

> Introducción
> ------------
>
> La idea es hacer un tipo de datos Money, basicamente para usos financieros,
> donde se necesitan decimales pero el punto flotante es demasiado inexacto.
> El tipo Money deberá soportar las funciones y operaciones estándares a
> Python.
>....

De mi experiencia en la adaptación al Euro que hemos sufrido en Europa (año 
2002), creo que sería conveniente, al hablar de precisión, diferenciar entre 
"precisión de la representación" y "precisión del cálculo". Como norma, en 
ningún momento un cambio de precisión debería implicar una modificación de 
los datos almacenados. Tan sólo se modifica su representación ó su cómputo.

La "Precisión de la Representación" se aplica cuando conviertes el dato a 
cadena de texto, y su aplicación no debe alterar el dato.

La "Precisión del Cálculo" es algo más complicado de determinar. En tu 
propuesta utilizas como precisión de cálculo la máxima precisión que tengan 
los operandos. Esto implica que, para asegurar la precisión de un determinado 
cálculo, sea necesario convertir la precisión de todos y cada uno de los 
operandos. Con que te dejes uno con una precisión alta, impondrá su precisión 
a toda la operación.

Mi consejo es que la precisión de cálculo debería quedar fijada previamente al 
cálculo. Siempre se puede cambiar la precisión de cálculo, pero lo normal 
será que quede fijada desde el inicio de la aplicación y que sólo se apliquen 
redondeos del dato cuando sea preciso.

O sea, haría que la precisión fuera un atributo de la clase.

Consideraría, además, la posibilidad de aceptar precisiones "negativas".
Estudia un poco los siguientes ejemplos:

>>> m=Money(3123.45)
Money(3123.4500)      # Default: Money.precision=4
>>> Money.precision=-3
>>> m
Money(3000)
>>> Money.precision=0
>>> m
Money(3123)
>>> n=m*Money(1)
>>> n,m
(Money(3123),Money(3123))
>>> n==m
True
>>> Money.precision=4
>>> n==m
False
>>> n,m
(Money(3123.00),Money(3123.45))


En cuanto a las conversiones de tipo, aplicaría la norma de convertir siempre 
hacia el tipo de dato más genérico. Considero que el tipo 'float' es más 
genérico que el 'Money', y no al revés como sugieres.

En cuanto a utilizar la "localización", consiste en obtener el modo de 
representar números de la configuración del sistema. Mírate 
'locale.localeconv()'


Como truco avanzado, se me ocurre que se podría implementar un operador de 
formato tal que así:

>>> "%(-3$)8s" % Money(3123)    # precision -3 en 8 columnas de texto
'    3000'

Esto se consigue añadiendo un método __getitem__ a la clase

def __getitem__(self,it):
    if it[-1]!='$':
        raise Exception, "Format Error with %s"%it[-1]

    try:
        v=int(it[:-1])
        s=self.toStr(v)
    except:
        s=self.toStr()

    return s


Sobre la licencia:

> Este código es de dominio público. En los módulos, asigné el copyright a
> PSF, falta verificar si hay que solicitar algo previamente.

Aunque se entiende de muchas maneras, técnicamente "dominio público" es algo 
que pertenece a todo el mundo, pero a nadie en concreto. Parece 
contradictorio con el hecho de que luego digas que lo cedes a la PSF.

El copyright (al menos en Europa) pertenece siempre al autor y es 
intransferible. En EEUU, la legislación es más permisiva, por lo que se 
recomienda poner explícitamente el "copyright". En Argentina no tengo ni idea 
de cómo va, pero en todo caso deberías ponerte a tí en el copyright.

La licencia que buscas es la "Licencia PSF", en la que se pasa la "propiedad" 
del software a la PSF para que lo ceda a terceros. No tengo claro si se puede 
hacer, ni cómo. Eso sí, cuidado con no confundir esta licencia con la 
"Licencia Python (CNRI)".


- -- 
Chema Cortes (py en ch3m4.org)
  http://py.ch3m4.org
    PGPKEY: mailto:pgpkey en ch3m4.org?subject=__PGPKEY__
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2-rc1-SuSE (GNU/Linux)

iD8DBQE/kJsPHLTQrABk8H0RArzsAKCd1mYvk7E7gqd4TRlaHBQ3LJJn7ACg+KY9
Ik9m5baodmGPp+Aytql9hvw=
=z9g1
-----END PGP SIGNATURE-----




Más información sobre la lista de distribución Python-es