2011-08-21 8 views
10

Aquí hay un código en un tutorial de django por el que estoy pasando. Nunca me he encontrado con la función súper en Python y la forma en que se usa aquí es diferente de los ejemplos que he visto en línea. Es decir, generalmente cuando usa super, ¿no tiene múltiples clases? Está en la última línea: super(Snippet, self).save(force_insert, force_update) ¿Podría explicar exactamente qué está pasando allí y cuál sería una forma alternativa de escribir eso? ¿Parece que el método de guardar se está llamando aquí?uso de la súper función de pitón en django modelo

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) 

Respuesta

24

super(Snippet, self) provoca Python que debe buscar en el MRO de la clase de uno mismo (es decir, self.__class__.mro() para la clase siguiente que aparece después de Snippet. Devuelve un objeto super que actúa como un proxy para esa clase. Es decir, llamar a un método en los actos objeto super como llamar a ese método en la clase.

super(Snippet, self).save(...) llama al método save de esa clase, con self unido al primer argumento.

Entonces super(Snippet, self).save(...) no llamará al Snippetsave método; llamará al método de otra clase save. Es tentador pensar que esta "otra clase" es la "clase principal" o "superclase" de Snippet, es decir, models.Model, pero que puede no ser cierto y es absolutamente incorrecto aprehender super de esta manera. La clase que finalmente representa super(Snippet, self) depende de self y, en particular, de su clase MRO.

Una muy buena descripción de MRO y super (¡completa con imágenes!) Se puede encontrar here.

3

No voy a explicar una vez más lo que se explica en unutbu clases súper, sin embargo, se obtiene el mismo efecto con el siguiente código:

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

Ésta no es una mejor manera de escribirlo, ya que, si se llega a Cambia la herencia de clase agregando una clase intermedia entre Model y Snippet, también deberías cambiar esta línea (lo que probablemente olvidarías). De todos modos, es bueno saberlo.

También puedo agregar que la súper instrucción solo funciona si la clase heredada se extiende desde el objeto, de lo contrario se obtiene una excepción.

+2

No se trata solo de cambiar los antepasados ​​de Snippet; si hay una cierta forma de herencia múltiple en una clase secundaria de Snippet, el resultado podría ser diferente al correcto 'super (Snippet, self)'. –

Cuestiones relacionadas