【问题标题】:Sub-classing float type in Python, fails to catch exception in __init__()在 Python 中对浮点类型进行子类化,无法在 __init__() 中捕获异常
【发布时间】:2009-12-20 17:51:35
【问题描述】:

在 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

【问题讨论】:

    标签: python exception-handling


    【解决方案1】:

    float 是不可变的,因此它的__init__initializer,基本上是一个空操作——在那里不会发生任何实质性的事情,因为self 对象不能被改变(如果它实际上是float 的一个实例,而不是一个子类——当然float 自己的__init__ 必须基于该假设运行;-)。

    因此,所有的动作都发生在__new__,即构造函数中,就像其他不可变类型如intstrtuple等一样。认为__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 异常类,效果会更好;-)。

    【讨论】:

      【解决方案2】:

      改用__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
      

      【讨论】:

      • 谢谢!,完美运行。关于"%.2f" % self,用什么方法进行字符串转换? float.__str__()?我以为是F.__str__(),其实不是,因为没有无限递归。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-10
      • 2021-04-03
      • 1970-01-01
      • 1970-01-01
      • 2012-10-27
      • 2012-02-09
      相关资源
      最近更新 更多