2011-12-23 41 views
18

Trong khi đọc mã OpenStack và tôi đã gặp phải điều này.Phương thức __init __() của đối tượng làm gì trong python?

Lớp học có tên 'Dịch vụ' kế thừa đối tượng của lớp cơ sở ', và sau đó trong phương thức __init__() của Dịch vụ, đối tượng được gọi là __init__. Mã liên quan như sau:

định nghĩa lớp:

class Service(object): 

và định nghĩa phương pháp init Dịch vụ của:

def __init__(self, host, binary, topic, manager, report_interval=None, 
      periodic_interval=None, *args, **kwargs): 

và một cuộc gọi đến siêu (các 'đối tượng' ở đây) trong init Dịch vụ của :

super(Service, self).__init__(*args, **kwargs) 

Tôi không hiểu cuộc gọi cuối cùng, object.__init__() điều gì thực tế Reason? có ai giúp được không?

Trả lời

14

Câu trả lời ngắn gọn là đối tượng .__ init __() phương pháp không có gì ngoại trừ kiểm tra rằng không có đối số đã được thông qua trong. Xem the source để biết chi tiết.

Khi kêu gọi một thể hiện của Dịch vụ, cuộc gọi super() sẽ uỷ thác cho đối tượng .__ init __() và không có gì sẽ xảy ra.

Tuy nhiên, khi được gọi trên một phiên bản của một lớp con của Dịch vụ, mọi thứ trở nên thú vị hơn. Cuộc gọi siêu() có thể ủy quyền cho một số lớp khác ngoài đối tượng, một lớp học là cha mẹ của cá thể nhưng không phải là phụ huynh của Dịch vụ. Để biết chi tiết về cách hoạt động của tính năng này và tại sao lại hữu ích, hãy xem bài đăng trên blog Python's Super Considered Super!

Ví dụ sau (hơi giả tạo) cho thấy cách một lớp con của Dịch vụ có thể gây ra siêu cuộc gọi trong Dịch vụ để được dẫn đến một lớp được gọi là Màu:

class Service(object): 
    def __init__(self, host, binary, topic, manager, report_interval=None, 
      periodic_interval=None, *args, **kwargs): 
     print 'Initializing Service' 
     super(Service, self).__init__(*args, **kwargs) 

class Color(object): 
    def __init__(self, color='red', **kwargs): 
     print 'Initializing Color' 
     self.color = color 
     super(Color, self).__init__(**kwargs) 

class ColoredService(Service, Color): 
    def __init__(self, *args, **kwds): 
     print 'Initializing Colored Service' 
     super(ColoredService, self).__init__(*args, **kwds) 

c = ColoredService('host', 'bin', 'top', 'mgr', 'ivl', color='blue') 

Trong ví dụ: việc khởi tạo diễn ra theo thứ tự sau:

  1. Khởi tạo màu Dịch vụ
  2. dịch vụ Khởi tạo
  3. Khởi tạo màu
  4. Initialize đối tượng - không làm gì ngoại trừ luận kiểm tra
+2

tham chiếu [Siêu chú ý của Python Super] (http://rhettinger.wordpress.com/2011/05/26/super-considered-super/) giúp ích rất nhiều. Cảm ơn! –

+1

Hàm tạo 'ColoredService' cho phép, ví dụ: 'foo = 'bar'' được truyền, nhưng điều này cuối cùng sẽ thất bại với' TypeError: object .__ init __() không có tham số'. Vì vậy, những gì là điểm trong đi qua '* args' và' ** kwargs' trong 'super' các cuộc gọi cho các lớp' Service' và 'Color'? Ví dụ của bạn sẽ làm việc giống nhau mà không có chúng (và sẽ mạnh mẽ hơn). – ekhumoro

+0

@ekhumoro Nhận xét đó nên được hướng dẫn tại các nhà văn của OpenStack. Phần '' * args'' là từ mã của họ và người gọi phải tôn trọng chữ ký đó. Tôi vừa thêm * Color * và * ColoredService * để hiển thị cách MRO có thể chuỗi từ * Service * đến * Color * to * object *. –

3

super()không phải lúc nào cũng trả về proxy cho lớp cha. Thay vào đó, nó trả về một proxy cho lớp tiếp theo trong MRO. Trong thừa kế đơn không có sự khác biệt giữa MRO và chuỗi kế thừa. Trong đa thừa kế, MRO có thể dẫn đến một lớp học trên các chuỗi thừa kế khác thay thế.

+0

nhưng không có nhiều thừa kế ở đây, khi dịch vụ được thừa hưởng trực tiếp từ đối tượng –

+0

@can .: Nhưng những gì được thừa hưởng từ 'Dịch vụ'? –

+0

Tôi đã đọc bài viết về MRO, và tôi nghĩ vì Dịch vụ kế thừa trực tiếp từ đối tượng, siêu() không có sự mơ hồ ở đây. Người thừa kế từ Dịch vụ không tạo nên sự khác biệt. –

1

object.__init__() không thực sự làm bất cứ điều gì, nhưng phải bao gồm cuộc gọi super() ngay cả khi một lớp chỉ có object làm lớp cha.

One big problem with 'super' is that it sounds like it will cause the superclass's copy of the method to be called. This is simply not the case, it causes the next method in the MRO to be called (...) People omit calls to super(...).init if the only superclass is 'object', as, after all, object.init doesn't do anything! However, this is very incorrect. Doing so will cause other classes' init methods to not be called.

http://fuhm.net/super-harmful/

+0

Nhưng lưu ý rằng mã ví dụ của OP sẽ thất bại nếu bất cứ thứ gì được truyền qua '* args' và' ** kwargs' (trừ khi nó chạy với python 2.5 hoặc cũ hơn). – ekhumoro

+0

bạn có thể giải thích ý tưởng của mình với nhiều chi tiết hơn không? @ekhumoro –

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