在Python中使用super执行父级函数

时间:2012-08-15 23:22:59

标签: python python-2.7 super

我在使用Python中的超级函数时遇到了一些问题。假设我有这两个类:

class A(object):
     x=5
     def p(self):
             print 'A'
     def f(self):
             self.p()
             self.x+=1

class B(A):
    def p(self):
             print 'B'
    def f(self):
             super(B, self).f()
             self.x*=2

b = B()
b.f()

然后b.x将等于12,但该函数将输出'B',而不是'A'。我需要的是执行A.p而不是B.p,我该如何实现呢?

感谢您的时间:)


编辑:好的,我认为你错过了一些关于我实际情况的细节,因为我的例子不好。让我们来看看真正的代码。我有这两个类(Django模型):

class Comment(Insert, models.Model):

    content = models.TextField()
    sender = models.ForeignKey('logic.User')
    sent_on = models.DateTimeField(auto_now_add=True)

    def __insert__(self):
        self.__notify__()

    def __notify__(self):
        receivers = self.retrieve_users()
        notif_type = self.__notificationtype__()
        for user in receivers:
            Notification.objects.create(
                object_id=self.id,
                receiver=user,
                sender_id=self.sender_id,
                type=notif_type
            )

    def __unicode__(self):
        return self.content

    class Meta:
        abstract = True


class UserComment(Comment):

    is_reply = models.BooleanField()
    reply_to = models.ForeignKey('self', blank=True,
                                null=True, related_name='replies')
    receiver = models.ForeignKey('User', related_name='comments')

    def __insert__(self):
        super(UserComment, self).__insert__()
        self.__notify__()

    def __notification__(self, notification):
        if self.is_reply:
            return '%s has replied your comment' % self.sender
        return super(UserComment, self).__notification__(notification)

    def __notify__(self):
        # Notification objects "should" be created by Comment's __notify__
        Update.objects.create(
            object_id=self.id,
            target=self.receiver,
            type=self.__updatetype__(),
        )

    @classmethod
    @cache(prop_name='_notificationtype')
    def __notificationtype__(cls):
        return NotificationType.objects.get(name='USER_COMMENT')

    @classmethod
    @cache(prop_name='_updatetype')
    def __updatetype__(cls):
        return UpdateType.objects.get(name='USER_COMMENT')

    def retrieve_users(self):
        return [self.receiver]  # retrieve_users MUST return an iterable

问题在于两种模型上的__insert____notify__方法。 __insert__是一种在第一次将对象记录到数据库时调用的方法,我主要将其用于通知目的。然后,这就是我想要做的事情:

  1. 创建UserComment对象并保存
  2. 调用UserComment实例的__insert__
  3. 致电评论__insert__,其中致电评论__notify__
  4. __notify__
  5. 调用UserComment实例的__insert__

    这可能是一种或多或少的方式,还是我必须重构我的代码? 再次感谢您的所有答案。

3 个答案:

答案 0 :(得分:5)

您只是说要执行A.p()

class B(A):
    def p(self):
        print 'B'
    def super_p(self):
        return A.p(self) # prints 'A'

如果您想确保A.p()被排除,最好的办法就是从B中的方法明确调用它。正如Rajesh所说,避免这种情况的最好方法是不要覆盖你打算在基类中调用的方法。

超类无法了解子类的任何信息。例如,如果您实例化子类B并且它继承方法x()并覆盖方法p(),那么当您调用x()时,将调用p()定义 B ,而不是A中的(overrridden)定义。这正是您应该期望的 - 您已经创建了一个混合类并覆盖了其中一个方法。

答案 1 :(得分:1)

请记住,self是指实例,因为b是B的实例,self.p()引用method p() in class B,而不是A.所以要么删除方法{{1来自B类或明确地从B调用p()

A's p()

或者创建A的pa静态方法并使用class B(A): def p(self): super(B, self).p() print 'B' def f(self): super(B, self).f() self.x*=2 从A类中的f()调用它,特别是如果您不需要从该方法访问该类,那么p a 'function' rather than a 'method'

A.p()

使用此B,输出为:

class A(object):
    x=5
    @staticmethod
    def p():
        print 'A'
    def f(self):
        A.p()
        self.x+=1

请注意B仅在>>> b = B() >>> b.f() A >>> b.x 12 >>> b.p() A B 来电时打印,而不是b.p()时打印。

答案 2 :(得分:0)

观察代码中事件的进展情况:

  

self.x = 5

     

self.x = 6

     

self.x = 12

鉴于您的代码,这是获得12作为输出的唯一方法。但是,如果我们从A类而不是B运行它,则会出现以下行为:

  

self.x = 5

     

self.x = 6

在我看来,你想要这种行为。唯一的区别在于行self.x += 2

这引出了一个更有趣的问题:为什么你希望(或者甚至期望)在将方法重载到不同的方法之后,子类的行为与其超级方法完全相同! A执行函数x+1,而B执行函数(x+1)*2,这显然是不同的。方法重载的根本目的是表现出与父类不同的行为,而 lo和behold ,它确实发生了!