I’m having some problems with the super function in Python. Suppose I have these two classes:
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()
Then b.x will equal 12, but the function will output ‘B’, not ‘A’. What I need is to execute A.p instead of B.p, how can I achieve that?
Thanks for your time 🙂
EDIT: Ok, I think you missed some details about my actual situation because of my poor example. Let’s get to real code. I have these two classes (Django models):
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
The problem is with __insert__ and __notify__ methods on both models. __insert__ is a method that gets called the first time an object is recorded to the DB, and I use it for notification purposes mainly. Then, this is what I want to do:
- Create a UserComment object and save it
- Call UserComment instance’s
__insert__ - Call Comment’s
__insert__, which should call Comment’s__notify__ - Call UserComment instance’s
__notify__from__insert__
Is this possible in a more or less easy way or do I have to refactor my code?
Thanks again for all your answers.
Remember that
selfrefers to an instance and sincebis an instance of B, self.p() refers tomethod p() in class B, not A. So either remove methodp()from class B or explicitly callA's p()from B as:Or make p a staticmethod of A and call it from f() in class A with
A.p(), especially if you don’t need access to the class from that method making p a ‘function’ rather than a ‘method’:With this B, the output is:
Note how B got printed only in the
b.p()call but not when it wasb.f().