web-dev-qa-db-ja.com

python super function in Django model

これが私が経験しているDjangoチュートリアルのいくつかのコードです。これまでpythonとここでの使用方法でスーパー関数に出くわしたことはありません。オンラインで見た例とは異なります。つまり、通常、superを使用する場合、複数のクラスがありませんか?最後の行にあります: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)
14
user637965

super(Snippet, self)により、Pythonは自己のクラスの [〜#〜] mro [〜#〜] を調べます(つまり、self.__class__.mro()Snippetの後にリストされているnextクラスの場合。プロキシとして機能するsuperオブジェクトを返します。つまり、superオブジェクトでメソッドを呼び出すことは、クラスでそのメソッドを呼び出すことと同じように機能します。

super(Snippet, self).save(...)は、そのクラスのsaveメソッドを呼び出し、selfを最初の引数にバインドします。

したがって、super(Snippet, self).save(...)Snippetsaveメソッドを呼び出しません。他のクラスのsaveメソッドを呼び出します。この「他のクラス」がSnippetの「親クラス」または「スーパークラス」、つまり_models.Model_であると考えたくなりますが、それは真実ではない可能性があり、理解することは絶対に間違っています。 superこのように。 super(Snippet, self)が最終的に表すクラスは、self、特にそのクラスのMROによって異なります。

MROsuper(写真付き!)の非常に良い説明が見つかります ここ

26
unutbu

Unutbuがスーパークラスで説明したことを再度説明することはしませんが、次のコードで同じ効果が得られます。

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

ModelとSnippetの間に中間クラスを追加してクラスの継承を変更する場合は、この行も変更する必要があるため、これは適切な記述方法ではありません(おそらく忘れてしまいます)。とにかく知っておくのは良いことです。

スーパー命令は、継承元のクラスがオブジェクトから拡張されている場合にのみ機能することも付け加えます。そうでない場合は、例外が発生します。

4
JC Plessis