在Python中子类化float类型,__init__()中的异常未被捕获
在Python 2.5中,我需要使用浮点数,并且想要修改__str__()
这个方法。同时,我还想知道当构造函数出错时该怎么处理。
为什么我不能捕捉到从float.__init__()
抛出的异常呢?
我该如何获取我自定义的浮点对象的数值?在我的代码中,我使用了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
2 个回答
8
试试用 __new__
这个方法:
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")
另外,“self”已经是一个浮点数了,所以不需要再写 float(self),直接用“self”就可以了:
def __str__(self):
return "%.2f" % self
24
float
是不可变的,这意味着它的 __init__
方法,通常叫做初始化器,基本上是个无操作——在这里不会发生什么实质性的事情,因为 self
对象是不能被改变的(前提是它真的是 float
的实例,而不是子类的实例——当然,float
自己的 __init__
方法必须基于这个假设来工作;-)。
因此,所有的实际操作都发生在 __new__
方法中,这个方法才是真正的构造器,就像其他不可变类型,比如 int
、str
、tuple
等等。很多人常常误以为 __init__
是构造器:其实不是,它接收一个已经构造好的对象作为第一个参数 self
,然后对它进行“初始化”(如果可能的话,也就是说,如果这个 self
是可变的!-)——真正的构造过程是在 __new__
中完成的。
所以,你的 float
子类应该这样开始:
class My_Number(float):
def __new__(cls, float_string):
try: return float.__new__(cls, float_string)
except (TypeError, ValueError): raise My_Error(float_string)
而且你可以去掉 __init__
,因为它并不需要。现在:
>>> 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
(当然,如果你定义了一个 My_Error
异常类,那效果会更好;-)。