2011-08-21 18 views
10

Oto kod w samouczku django, przez który przechodzę. Nigdy wcześniej nie spotkałem się z super funkcją w Pythonie, a sposób jej użycia różni się od przykładów, które widziałem w Internecie. Np. Zazwyczaj gdy używasz super, nie masz wielu zajęć? To jest w ostatniej linii: super(Snippet, self).save(force_insert, force_update) Czy mógłbyś wyjaśnić dokładnie, co się tam dzieje i jaki byłby alternatywny sposób napisania tego. Po prostu wydaje się, że metoda zapisu nazywa się tutaj?użycie superpikonu python w modelu 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) 

Odpowiedz

24

super(Snippet, self) powoduje Python spojrzeć w MRO klasy jaźni (tj self.__class__.mro() dla klasy obok wymienionych po Snippet. Zwraca super obiekt, który działa jako serwer proxy dla tej klasy. To znaczy, wywołanie metody na super obiektu działa jak wywołanie tej metody w klasie.

super(Snippet, self).save(...) wzywa save metody tej klasy, w self związany z pierwszym argumentem.

Tak więc super(Snippet, self).save(...) nie będzie wywoływać metody Snippet 's save; to wywoła inną metodę klasy innej klasy. Kusi mnie myśl, że ta "inna klasa" jest "klasą nadrzędną" lub "nadklasą" z Snippet, to jest models.Model, ale to może nie być prawdą i absolutnie niewłaściwe jest zatrzymanie w ten sposób super. Która klasa ostatecznie reprezentuje klasę super(Snippet, self), zależy od self, a w szczególności od MRO jej klasy.

Bardzo dobry opis MRO i super (wraz ze zdjęciami!) Można znaleźć here.

3

nie będę tłumaczyć ponownie co unutbu wyjaśnione na Super klas, jednak można uzyskać ten sam efekt z następującego kodu:

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

nie jest to lepszy sposób, aby zapisać go, ponieważ, jeśli się do zmień dziedziczenie klas, dodając klasę pośrednią między Modelem a Snippet, musiałbyś również zmienić tę linię (co najprawdopodobniej zapomnisz). W każdym razie dobrze wiedzieć.

Mogę również dodać, że super instrukcja działa tylko wtedy, gdy klasa, z której dziedziczysz, rozciąga się od obiektu, w przeciwnym razie otrzymasz wyjątek.

+2

To nie tylko zmiana przodków Snippet; jeśli istnieje pewna forma dziedziczenia wielokrotnego w klasie podrzędnej klasy, wynik może być inny niż poprawny 'super (Snippet, self)'. –