Subclasificando el tipo flotante en Python, no se puede detectar la excepción en __init __ ()

En Python 2.5 necesito usar números flotantes con un método __str__() modificado. También necesito saber cuándo falla el constructor.

¿Por qué no puedo detectar las excepciones generadas desde float.__init__() ?

¿Cuál es la mejor manera de consultar el valor numérico de mi objeto flotante derivado? En mi código estoy usando float(self) .

 class My_Number(float): def __init__(self, float_string): try: super(My_Number, self).__init__(float_string) except (TypeError, ValueError): raise My_Error(float_string) def __str__(self): if int(float(self)) == float(self): return str(int(float(self))) else: return str(round(float(self), 2)) >>> n = My_Number('0.54353') >>> print n 0.54 >>> n = My_Number('5.0') >>> print n 5 >>> n = My_Number('foo') Traceback (most recent call last): File "", line 1, in  ValueError: invalid literal for float(): foo 

float es inmutable, por lo tanto su __init__ , el inicializador , es básicamente un no-op (nada sustancial puede suceder allí), porque el self objeto no puede ser alterado (si en realidad es una instancia de float lugar de una subclase), pero por supuesto el propio __init__ debe operar en esa suposición ;-).

Por lo tanto, toda la acción sucede en __new__ , el constructor propiamente dicho, al igual que para otros tipos inmutables como int , str , tuple , etc. Es un error común creer que __init__ es un constructor: no lo es, toma un objeto ya construido como su primer argumento, self , y lo “inicializa” (si es posible, es decir, ¡si ese self es mutable! -) la construcción en sí sucede en __new__ .

Por lo tanto, su subclase float debe comenzar:

 class My_Number(float): def __new__(cls, float_string): try: return float.__new__(cls, float_string) except (TypeError, ValueError): raise My_Error(float_string) 

y puede eliminar el __init__ , que no es necesario. Ahora:

 >>> n = My_Number('foo') Traceback (most recent call last): File "", line 1, in  File "", line 4, in __new__ NameError: global name 'My_Error' is not defined 

(por supuesto, funcionaría incluso mejor si tuviera una clase de excepción My_Error definida ;-).

prueba __new__ en __new__ lugar:

 class F(float): def __new__(cls, *arg, **kw): try: return float.__new__(cls, *arg, **kw) except ValueError: raise Exception("foo") print F("3.5") print F("asdf") 

También “self” es un flotador ya que no hay necesidad de decir float (self), solo “self” hará:

 def __str__(self): return "%.2f" % self