2016-03-11 23 views
6

Trong Python 3.4, tôi muốn tạo một lớp con của float - một thứ có thể được sử dụng trong các phép toán và boolean như float, nhưng có chức năng tùy chỉnh khác và có thể nhận được đối số lúc khởi tạo điều khiển chức năng đó. (Cụ thể, tôi muốn có một tuỳ chỉnh __str__ và thông số được sử dụng trong phương pháp đó.)Python: Có thể một lớp con của float lấy thêm đối số trong hàm tạo của nó không?

Tuy nhiên, tôi dường như không thể có được một lớp con của float để có hàm tạo hai đối số chức năng. Tại sao? Đây có phải chỉ đơn giản là một hạn chế về việc mở rộng các kiểu dựng sẵn?

Ví dụ:

class Foo(float): 
    def __init__(self, value, extra): 
     super().__init__(value) 
     self.extra = extra 

Bây giờ nếu tôi cố gắng Foo(1,2) tôi nhận được:

TypeError: float() takes at most 1 argument (2 given) 

Đáng ngạc nhiên, lập luận __init__ mới của tôi được thực thi quá, vì vậy nếu tôi làm Foo(1) tôi nhận được:

TypeError: __init__() missing 1 required positional argument: 'extra' 

Thỏa thuận ở đây là gì? Tôi đã thực hiện những điều tương tự với các kiểu con của list và đã rất ngạc nhiên khi nó không hoạt động trên float.

+3

Related: http://stackoverflow.com/questions/1936457/sub-classing-float-type-in- python-fail-to-catch-exception-in-init –

+2

Không phải là câu trả lời cho câu hỏi của bạn, mà là một giải pháp cho vấn đề của bạn: http://ideone.com/nIPim9 –

+0

Thú vị, @ Robᵩ. Có vẻ như trọng trách '__new__' có thể là cách để làm những gì tôi muốn, nhưng không chắc chắn chính xác làm thế nào để làm cho công việc đó được nêu ra. –

Trả lời

7

Vì phao không thay đổi, bạn cũng phải ghi đè lên __new__. Sau đây nên làm những gì bạn muốn:

class Foo(float): 
    def __new__(self, value, extra): 
     return float.__new__(self, value) 
    def __init__(self, value, extra): 
     float.__init__(value) 
     self.extra = extra 

foo = Foo(1,2) 
print(str(foo)) 
1.0 
print(str(foo.extra)) 
2 

Xem thêm Sub-classing float type in Python, fails to catch exception in __init__()

+0

Vâng, đây là phương pháp làm việc - cảm ơn! Tôi vẫn còn bối rối bởi tại sao điều này là cần thiết, mặc dù. Đối với phương thức '__init__' của bạn,' self' là 'float' không phải là' Foo', đúng không? Bởi vì chúng ta đã tạo nó thông qua 'float .__ new__'? –

+0

Trên thực tế, http://stackoverflow.com/a/13534717/204131 chỉ ra rằng 'float .__ new__' được thông qua một tham số' Foo', do đó, nó sẽ tạo ra một thể hiện của 'Foo' thay vì float. –

3

các giải pháp của cgogolin là đúng. nó giống như vậy với một lớp học bất biến khác như int, str, ... Nhưng tôi sẽ viết:

class Foo(float): 
    def __new__(cls, value, extra): 
     return super().__new__(cls, value) 
    def __init__(self, value, extra): 
     float.__init__(value) 
     self.extra = extra 
+0

ở đâu là cgogolin? –

+0

câu trả lời của anh ấy ở trên – qvpham

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