2009-12-20 68 views
9

在Python 2.5上,我需要使用帶有修改的__str__()方法的浮點數。另外我需要知道構造函數何時失敗。Python中的子類float類型無法捕獲__init中的異常__()

爲什麼我無法捕捉到從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 

回答

17

float是不可變的,因此它的__init__,初始化程序基本上是沒有操作 - 沒有什麼實質上可以發生在那裏,是導致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異常類;-)。

+0

Works !,感謝您的解釋。 – Ricardo 2009-12-20 18:20:38

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") 

而且 「自我」 是一個浮動已經所以沒有必要說浮動(個體經營),只是 「自我」 會做:

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

謝謝!,工作完美。關於''%.2f「%self',使用什麼方法進行字符串轉換? '浮.__ STR __()'?我認爲它不是'F .__ str __()',因爲沒有無限遞歸。 – Ricardo 2009-12-20 18:25:31

相關問題