2011-11-04 28 views
8

thể trùng lặp:
Can Super deal with multiple inheritance?gọi init cho nhiều lớp cha với siêu?

Python thừa kế? Tôi có một cấu trúc lớp (bên dưới), và muốn lớp con gọi số __init__ của cả hai cha mẹ. Điều này có thể thực hiện theo cách 'siêu' hay chỉ là một ý tưởng khủng khiếp?

class Parent1(object): 
    def __init__(self): 
     self.var1 = 1 

class Parent2(object): 
    def _init__(self): 
     self.var2 = 2 

class Child(Parent1, Parent2): 
    def __init__(self): 
     ## call __init__ of Parent1 
     ## call __init__ of Parent2 
     ## super(Child, self).__init__() 

Trả lời

17

Invocation qua super không gọi tất cả các bậc cha mẹ, nó gọi chức năng tiếp theo trong chuỗi MRO. Đối với điều này để làm việc đúng cách, bạn cần phải sử dụng super trong tất cả các __init__ s:

class Parent1(object): 
    def __init__(self): 
     super(Parent1, self).__init__() 
     self.var1 = 1 

class Parent2(object): 
    def __init__(self): 
     super(Parent2, self).__init__() 
     self.var2 = 2 

class Child(Parent1, Parent2): 
    def __init__(self): 
     super(Child, self).__init__() 

Trong Python 3, bạn có thể sử dụng super() thay vì super(type, instance).

+0

Tôi đọc nhiều câu hỏi và câu trả lời khác, bạn là người duy nhất chỉ ra cách 'super()' gọi là "hàm tiếp theo trong chuỗi MRO". Một tuyên bố đơn giản nhưng rất quan trọng thực sự. – MikeyE

26

Ý tưởng về super() là bạn không cần phải bận tâm gọi __init__() phương pháp cả superclasses' riêng - super() sẽ chăm sóc nó, miễn là bạn sử dụng nó một cách chính xác - xem Raymond Hettinger's "Python’s super() considered super!" cho một lời giải thích.

Điều đó nói rằng, tôi thường thấy những bất lợi của super() đối với các cuộc gọi hàm tạo lớn hơn các ưu điểm. Ví dụ, tất cả các nhà xây dựng của bạn cần phải cung cấp một đối số **kwargs bổ sung, tất cả các lớp phải cộng tác, các lớp bên ngoài không cộng tác cần có trình bao bọc, bạn phải cẩn thận rằng mỗi tên thông số của hàm tạo là duy nhất trên tất cả các lớp của bạn, v.v.

vì vậy, thường xuyên hơn không, tôi nghĩ rằng đó là dễ dàng hơn để đặt tên một cách rõ ràng các phương pháp lớp cơ sở mà bạn muốn gọi cho constructor gọi:

class Child(Parent1, Parent2): 
    def __init__(self): 
     Parent1.__init__(self) 
     Parent2.__init__(self) 

tôi sử dụng super() cho các chức năng mà có một nguyên mẫu được bảo đảm, như __getattr__() , Tuy nhiên. Không có bất lợi trong những trường hợp này.

7

Bạn chỉ có thể gọi cho họ trực tiếp với Parent.__init__(self):

class Parent1(object): 
    def __init__(self): 
        self.var1 = 1 

class Parent2(object): 
    def _init__(self): 
        self.var2 = 2 

class Child(Parent1, Parent2): 
    def __init__(self): 
     Parent1.__init__(self) 
     Parent2.__init__(self) 
Các vấn đề liên quan