использование суперфункции python в модели django - PullRequest
12 голосов
/ 22 августа 2011

Вот некоторый код в уроке по django, через который я прохожу.Я никогда раньше не сталкивался с суперфункцией в python, и то, как она используется здесь, отличается от примеров, которые я видел в Интернете.Т.е. обычно, когда вы используете супер, у вас нет нескольких классов?Это в последней строке: 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)

Ответы [ 2 ]

26 голосов
/ 22 августа 2011

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 (в комплекте с картинками!) Можно найти здесь .

4 голосов
/ 22 августа 2011

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

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

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

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

...