Executing parent function with super in Python

I'm having issues with superfunctioning 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() bf() 

Then bx will be 12, but the function will output "B" and not "A". I need to execute Ap instead of Bp, how can I achieve this?

Thank you for your time:)


EDIT: Well, I think you missed some details about my real situation due to my bad example. Let me get the 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 __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 the __insert__ and __notify__ on both models. __insert__ is the method that is called the first time the object is written to the database, and I use it for notification purposes mainly. Then this is what I want to do:

  • Create a UserComment Object and Save It
  • Invoking UserComment __insert__
  • Comment on __insert__ , which should call Comment __notify__
  • Calling UserComment __notify__ from __insert__

Is this possible more or less easy or do I need to reorganize my code?
Thanks again for all your answers.

+4
source share
3 answers

Remember that self refers to an instance, and since b is an instance of B, self.p () refers to method p() in class B , not A. Therefore, we either remove the p() method from class B or explicitly call A p() from B as:

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

Or make pa staticmethod from A and call it from f () in class A using Ap() , especially if you do not need access to the class from this method, creating p a "function" and not a "method" :

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

In this case, B output:

 >>> b = B() >>> bf() A >>> bx 12 >>> bp() A B 

Note that B was only printed in a call to bp() , but not when it was bf() .

+1
source

You just say you want to execute Ap() :

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

If you want Ap() be explicit, the best way is to explicitly call it from your method in B As Rajesh said, the best way to avoid this situation is to not override the methods that you intend to call in the base class.

There is no way for the superclass to know anything about the subclass. For example, if you create an instance of subclass B and inherit the x() method and override the p() method, then when you call x() , it will call the definition of p() in B , not the (overridden) definition in A. This is exactly what you should expect - you created a hybrid class and redefined one of the methods.

+5
source

Keep track of events in your code:

self.x = 5

self.x = 6

self.x = 12

Given your code, this is the only way to get 12 as output. If we ran it from class A instead of B, the following behavior would occur:

self.x = 5

self.x = 6

It seems to me that you want this behavior. The only difference in the line is self.x += 2 .

This leads us to the more interesting question of why you wanted (or even expected) that the child class behaved exactly like its super method after overloading the method on something else! A performs the function x+1 , and B performs the function (x+1)*2 , which is obviously different. The main goal of method overloading is to exhibit different behavior from the parent class, and there it was!

0
source

All Articles