On Python 2.5 I need to use float numbers with a modified __str__()
method. Also I need to know when the constructor fails.
Why I can't catch exceptions raised from float.__init__()
?
What is the best way to consult the numeric value of my derived float object? In my code I'm using 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 "<stdin>", line 1, in <module>
ValueError: invalid literal for float(): foo
float
is immutable, therefore its __init__
, the initializer, is basically a no-op -- nothing substantial can happen there, because the self
object cannot be altered (if it's actually an instance of float
rather than of a subclass -- but of course float
's own __init__
must operate on that assumption;-).
Therefore, all the action happens in __new__
, the constructor proper, just like for other immutable types like int
, str
, tuple
, and so on. It's a common mistake to believe that __init__
is a constructor: it's not, it takes an already-constructed object as its first argument, self
, and "initializes" it (if feasible, i.e., if that self
is mutable!-) -- the construction itself happens in __new__
.
So, your float
subclass should start:
class My_Number(float):
def __new__(cls, float_string):
try: return float.__new__(cls, float_string)
except (TypeError, ValueError): raise My_Error(float_string)
and you can remove the __init__
, which is not needed. Now:
>>> n = My_Number('foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __new__
NameError: global name 'My_Error' is not defined
(of course, it would work even better if you did have a My_Error
exception class defined;-).
try __new__
instead:
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")
Also "self" is a float already so no need to say float(self), just "self" will do:
def __str__(self):
return "%.2f" % self
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With