2009-12-20 22 views
9

Trên Python 2.5 Tôi cần sử dụng các số phao với phương pháp __str__() đã sửa đổi. Ngoài ra tôi cần phải biết khi nào constructor thất bại.Loại phao phân lớp trong Python, không bắt ngoại lệ trong __init __()

Tại sao tôi không thể bắt ngoại lệ được nêu từ float.__init__()?

Cách tốt nhất để tham khảo giá trị số của đối tượng nổi có nguồn gốc của tôi là gì? Trong mã của tôi, tôi đang sử dụng 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 

Trả lời

17

float là không thay đổi, do đó, __init__, bộ khởi tạo , về cơ bản là không có gì - không có gì đáng kể có thể xảy ra ở đó, gây ra các đối tượng self không thể thay đổi (nếu nó thực sự là một thể hiện của float chứ không phải là một phân lớp - nhưng tất nhiên float 's riêng __init__ phải hoạt động trên giả định ;-).

Vì vậy, tất cả các hành động xảy ra trong __new__, các nhà xây dựng thích hợp, giống như đối với loại không thay đổi khác như int, str, tuple, và vân vân. Đó là một sai lầm phổ biến khi tin rằng __init__ là một hàm tạo: không phải, nó cần một đối tượng đã được xây dựng làm đối số đầu tiên, self và "khởi tạo" nó (nếu khả thi, nếu self đó có thể thay đổi! -) - tự động xây dựng trong __new__.

Vì vậy, float lớp con của bạn nên bắt đầu:

class My_Number(float): 
    def __new__(cls, float_string): 
    try: return float.__new__(cls, float_string) 
    except (TypeError, ValueError): raise My_Error(float_string) 

và bạn có thể loại bỏ các __init__, đó là không cần thiết. Bây giờ là:

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

(tất nhiên, nó sẽ làm việc tốt hơn nếu bạn đã có một lớp My_Error ngoại lệ được định nghĩa ;-).

+0

Hoạt động !, cảm ơn lời giải thích. – Ricardo

7

thử __new__ thay vì:

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

Cũng "tự" là một phao đã vì vậy không cần thiết phải nói float (tự), chỉ cần "tự" sẽ làm:

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

Cảm ơn !, đã hoạt động hoàn hảo. Về ''% .2f "% self', phương thức nào được sử dụng để chuyển đổi chuỗi? 'float .__ str __()'? Tôi nghĩ đó là 'F .__ str __()' mà nó không phải là, bởi vì không có đệ quy vô hạn. – Ricardo

Các vấn đề liên quan