4

我在 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()

然后 bx 将等于 12,但该函数将输出“B”,而不是“A”。我需要的是执行 Ap 而不是 Bp,我该如何实现?

谢谢你的时间 :)


编辑:好的,我认为你错过了一些关于我的实际情况的细节,因为我的例子很糟糕。让我们来看看真正的代码。我有这两个类(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. 调用 Comment's __insert__,它应该调用 Comment's__notify__
  4. 调用 UserComment 实例的__notify__from__insert__

这可能以或多或少的简单方式实现,还是我必须重构我的代码?
再次感谢您的所有回答。

4

3 回答 3

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()时,它将调用Bp()中的定义,而不是 A 中的(覆盖)定义。这正是您应该期望的 - 您'已经创建了一个混合类并重写了其中一个方法。

于 2012-08-15T23:28:20.613 回答
1

请记住,它self指的是一个实例,因为b它是 B 的一个实例,所以 self.p() 指的是method p() in class B,而不是 A。所以要么p()从类 B 中删除方法,要么从 B 显式调用A's p()

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

或者制作 A 的 pa staticmethod 并从 A 类中的 f() 调用它A.p(),特别是如果您不需要从该方法访问该类,使 p成为“函数”而不是“方法”

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 如何仅在b.p()调用中打印,而不是在调用时打印b.f()

于 2012-08-16T01:07:06.870 回答
0

观察代码中事件的进展:

自我.x = 5

自我.x = 6

自我.x = 12

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

自我.x = 5

自我.x = 6

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

这将我们引向一个更有趣的问题,即为什么在将方法重载为不同的方法后,您希望(甚至期望)子类的行为与其父类的方法完全相同!A执行功能x+1,而B执行功能(x+1)*2,这显然是不同的。方法重载的根本目的是表现出与父类不同的行为,你,它做到了!

于 2012-08-15T23:47:01.083 回答