Python中的子类化浮点类型无法捕获__init __()中的异常

Ric*_*rdo 10 python exception-handling

在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
Run Code Online (Sandbox Code Playgroud)

Ale*_*lli 19

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)
Run Code Online (Sandbox Code Playgroud)

你可以删除__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
Run Code Online (Sandbox Code Playgroud)

(当然,如果你确实有一个My_Error异常类,它会更好地工作;-).


zzz*_*eek 7

试着__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")
Run Code Online (Sandbox Code Playgroud)

"自我"也是一个浮动,所以不需要说浮动(自我),只是"自我"会做:

def __str__(self):
    return "%.2f" % self
Run Code Online (Sandbox Code Playgroud)