Execute parent's function with super in Python
我对Python中的超级函数有一些问题。假设我有这两个类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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,我如何才能做到这一点?
感谢您的时间:)
编辑:好吧,我想你错过了一些关于我实际情况的细节,因为我的例子不好。让我们开始真正的代码。我有这两门课(姜戈模特):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 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 |
问题出在两个模型上的
这是可以用一种或多或少简单的方式实现的,还是我必须重构我的代码?再次感谢您的回答。
你只是说你想执行
1 2 3 4 5 | class B(A): def p(self): print 'B' def super_p(self): return A.p(self) # prints 'A' |
如果要确保执行
超类不可能知道子类的任何信息。例如,如果实例化子类B,它继承一个方法
记住,
1 2 3 4 5 6 7 | class B(A): def p(self): super(B, self).p() print 'B' def f(self): super(B, self).f() self.x*=2 |
或者使p成为a的staticMethod,并使用
1 2 3 4 5 6 7 8 | class A(object): x=5 @staticmethod def p(): print 'A' def f(self): A.p() self.x+=1 |
使用此b,输出为:
1 2 3 4 5 6 7 8 | >>> b = B() >>> b.f() A >>> b.x 12 >>> b.p() A B |
注意b是如何只在
注意代码中事件的进展:
self.x = 5
self.x = 6
self.x = 12
根据您的代码,这是获得12作为输出的唯一方法。但是,如果我们从A类而不是B类运行它,则会出现以下行为:
self.x = 5
self.x = 6
在我看来,你想要这种行为。唯一的区别是
这就引出了一个更有趣的问题,即在您将该方法重载为其他方法之后,为什么您希望(甚至期望)子类精确地表现其超级方法!