Использование суперфункции python в модели django

Вот какой код в учебнике django, который я переживаю. Я никогда не сталкивался с суперфункцией в python раньше, и способ, которым она здесь используется, отличается от примеров, которые я видел в Интернете. I.e., обычно, когда вы используете супер, разве у вас нет нескольких классов? Это в последней строке: super(Snippet, self).save(force_insert, force_update) Не могли бы вы точно объяснить, что там происходит и что будет альтернативным способом написать это. Кажется, что метод save вызывается здесь?

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)

Ответ 1

super(Snippet, self) заставляет Python смотреть в MRO класса self (т.е. self.__class__.mro() для следующего класса, указанного после Snippet. Он возвращает объект super, который действует как прокси для этого класса. То есть вызов метода в объекте super действует как вызов этого метода в классе.

super(Snippet, self).save(...) вызывает этот метод класса save, при этом self привязан к первому аргументу.

Итак, super(Snippet, self).save(...) не будет вызывать метод Snippet save; он вызовет некоторый другой метод класса save. Заманчиво думать, что этот "другой класс" - это "родительский класс" или "суперкласс" Snippet, т.е. models.Model, но это может быть неверно, и совершенно неправильно воспринимать super таким образом. Какой класс super(Snippet, self) в конечном итоге представляет, зависит от self и, в частности, его класса MRO.

Очень хорошее описание MRO и super (в комплекте с картинками!) можно найти здесь.

Ответ 2

Я больше не буду объяснять, что unutbu объяснил на суперклассах, однако вы получите тот же эффект со следующим кодом:

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

Это НЕ лучший способ написать его, поскольку, если вы приступите к изменению наследования класса, добавив промежуточный класс между Model и Snippet, вам также придется изменить эту строку (что вы, скорее всего, забудете). В любом случае, это хорошо, что нужно знать.

Я также могу добавить, что супер-команда работает только в том случае, если класс, который вы наследуете, распространяется от объекта, иначе вы получите исключение.