2011-08-21 37 views
10

Đây là một số mã trong hướng dẫn django mà tôi sẽ trải qua. Tôi đã không bao giờ đi qua các chức năng siêu trong python trước và cách nó được sử dụng ở đây là khác nhau từ các ví dụ tôi đã nhìn thấy trực tuyến. Tức là, thường khi bạn sử dụng siêu, bạn không có nhiều lớp học? Đó là dòng cuối cùng: super(Snippet, self).save(force_insert, force_update) Bạn có thể giải thích chính xác những gì đang xảy ra ở đó và điều gì sẽ là một cách thay thế để viết điều đó. Nó chỉ có vẻ như phương pháp tiết kiệm được gọi là chính nó ở đây?sử dụng chức năng siêu python trong mô hình django

class Snippet(models.Model): 
    title = models.CharField(max_length=255) 
    language = models.ForeignKey(Language) 
    author = models.ForeignKey(User) 
    description = models.TextField() 
    description_html = models.TextField(editable=False) 
    code = models.TextField() 
    highlighted_code = models.TextField(editable=False) 
    tags = TagField() 
    pub_date = models.DateTimeField(editable=False) 
    updated_date = models.DateTimeField(editable=False) 

    class Meta: 
     ordering = ['-pub_date'] 

    def __unicode__(self): 
     return self.title 

    def save(self, force_insert=False, force_update=False): 
     if not self.id: 
      self.pub_date = datetime.datetime.now() 
     self.updated_date = datetime.datetime.now() 
     self.description_html = markdown(self.description) 
     self.highlighted_code = self.highlight() 
     super(Snippet, self).save(force_insert, force_update) 

Trả lời

24

super(Snippet, self) gây Python để tìm trong các MRO của lớp tự (ví dụ self.__class__.mro() cho lớp tiếp theo liệt kê sau Snippet. Nó trả về một đối tượng super hoạt động như một proxy cho lớp đó. Đó là,

gọi một phương thức trên các hành vi đối tượng super như gọi rằng phương pháp trên lớp.

super(Snippet, self).save(...) gọi phương thức save của lớp đó, với self ràng buộc với đối số đầu tiên.

Vì vậy, super(Snippet, self).save(...) sẽ không gọi phương thức Snippet 's save; nó sẽ gọi phương thức save của lớp khác. Thật là hấp dẫn khi nghĩ rằng "lớp khác" là "lớp cha" hoặc "siêu lớp" của Snippet, nghĩa là, models.Model, nhưng điều đó có thể không đúng và hoàn toàn sai khi bắt giữ super theo cách này. Lớp nào super(Snippet, self) cuối cùng đại diện phụ thuộc vào self và đặc biệt là MRO của lớp.

Mô tả rất tốt về MROsuper (hoàn chỉnh với ảnh!) Có thể được tìm thấy here.

3

Tôi sẽ không giải thích một lần nữa những gì unutbu giải thích trên lớp siêu, tuy nhiên bạn có được tác dụng tương tự với đoạn mã sau:

models.Model.save(self, force_insert, force_update) 

này KHÔNG phải là một cách tốt hơn để viết nó từ đó, nếu bạn đến thay đổi kế thừa lớp bằng cách thêm một lớp trung gian giữa Model và Snippet bạn cũng sẽ phải thay đổi dòng này (mà bạn sẽ rất có thể quên). Dù sao thì đó là một điều tốt để biết.

Tôi cũng có thể thêm rằng lệnh siêu chỉ hoạt động nếu lớp bạn kế thừa từ mở rộng từ đối tượng, nếu không bạn sẽ nhận được một ngoại lệ.

+2

Không chỉ khi tổ tiên của Snippet bị thay đổi; nếu có một dạng đa thừa kế nhất định trong một lớp con của Snippet, kết quả có thể khác với 'super (Snippet, self)' chính xác. –

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