2012-02-13 39 views
5
In [5]: class a(object): 
    ...:  def __init__(self): 
    ...:   print "In class a" 
    ...:   self.a = 1 
    ...:   
In [6]: class b(object): 
    ...:  def __init__(self): 
    ...:   print "In class b" 
    ...:   self.b = 2 
    ...:   
    ...:   

In [7]: class c(b, a): 
    ...:  pass 
    ...: 
In [8]: c.mro() 
Out[8]: 
[<class '__main__.c'>, 
<class '__main__.b'>, 
<class '__main__.a'>, 
<type 'object'>] 

In [9]: obj = c() 
In class b 

In [10]: obj.__dict__ 
Out[10]: {'b': 2} 

Giá trị mặc định __init__ phương pháp của lớp c được kêu gọi obj sáng tạo, mà trong nội bộ gọi __init__ chỉ lớp b.Hành vi của Mutlple thừa kế trong python

Theo hiểu biết của tôi, nếu tôi kế thừa từ 2 lớp, đối tượng lớp dẫn xuất của tôi phải có các biến từ cả hai lớp (trừ khi chúng là riêng tư cho các lớp đó).

Câu hỏi của tôi: Tôi có sai khi mong đợi đối tượng dẫn xuất của tôi chứa các biến từ cả hai lớp không? Nếu vậy, tại sao? Không nên __init__ của lớp a cũng được gọi? Điều gì sẽ xảy ra trong ngôn ngữ như C++?

+0

câu trả lời của jcollado là chính xác. Xem [answer] (http://stackoverflow.com/q/607186) để biết thêm chi tiết về cách 'super' hoạt động. – perelman

Trả lời

8

Trong trăn, phương pháp khởi tạo từ lớp trên không được gọi theo mặc định. Để thực hiện điều đó, bạn phải gọi rõ ràng chúng bằng cách sử dụng super như sau:

class a(object): 
    def __init__(self): 
     super(a, self).__init__() 
     print "In class a" 
     self.a = 1 

class b(object): 
    def __init__(self): 
     super(b, self).__init__() 
     print "In class b" 
     self.b = 2 

class c(b, a): 
    pass 

obj = c() 

Ví dụ đầu ra.

Trong lớp một
Trong lớp b

Edit: Về lý do tại sao các công trình này theo cách này, tôi muốn nói rằng đó là một quyết định thiết kế dựa trên The Zen of of Python:

Explicit là tốt hơn là ngầm.

+0

tại sao phương thức 'super (b, self) .__ init __()' gọi '__init__' của a, a không phải là siêu lớp của b, có nghĩa là cú pháp gọi đối tượng tiếp theo trong chuỗi mro không? – avasal

+0

@avasal, có lệnh gọi 'super' sẽ tìm ra phương thức có sẵn tiếp theo trong chuỗi mro. Lưu ý rằng mã chỉ được sử dụng bởi vì 'object .__ init__' tồn tại và được gọi là không có đối số: nếu' __init__' trong các lớp lấy một đối số, hoặc bạn muốn propogate một phương thức khác thì bạn có thể cần một lớp stub can thiệp để chấm dứt chuỗi các cuộc gọi 'super'. Xem thêm http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ – Duncan

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