1
class Animal(object):

    def __init__(self, name):
        self.name = name

    def intro(self):
        return "I am an animal named %s" %self.name


class Dog(Animal):

    def intro(self):
        return "I am a dog named %s" %self.name 


class Puppy(Dog):

    def intro(self):
        return "I am a puppy named %s" %self.name


dizzy = Puppy("Dizzy")

What would I do if I wanted a single instance of dizzy.intro() to return the Dog or the Animal intro method? i.e., I don't want to do a super call within the class to override the method, but I want just a one-off way to specify which of the three intro methods I'm using on this specific instance of dizzy?

thumbtackthief
  • 6,093
  • 10
  • 41
  • 87
  • 1
    *I don't want to do a super call within the class*. Why not? And what does *one-off way to specify which of the three .. methods* look like for you, can you elaborate on that? – Martijn Pieters Jan 02 '16 at 15:41
  • It was an interview question. I'm not really sure what a use case would be. But for this example, I mean if I wanted the `dizzy` object only to return either "I am an animal/dog named Dizzy", is there a way to do that? – thumbtackthief Jan 02 '16 at 15:47
  • 1
    Perhaps the interviewer is trying to gage your ability to ask for clarifications too? And `super()` can be used *outside* the method too. – Martijn Pieters Jan 02 '16 at 15:49
  • Ah--I see my mistake now. I just had the syntax of the `super` call messed up. Would you like to write up an answer for the rep? Otherwise I will. – thumbtackthief Jan 02 '16 at 16:20

2 Answers2

2

You have several options, and all can be used outside the instance.

You could use super(); it takes a class and an instance, and will find the next method in the MRO order:

super(Puppy, dizzy).intro()  # uses Dog.intro()
super(Dog, dizzy).intro()    # uses Animal.intro()

or you could use the unbound method on the class, passing in the instance manually:

Dog.intro(dizzy)
Animal.intro(dizzy)

This basically hardcodes what method you use, while using super() remains dynamic and will adjust when adding in more complex class hierarchies.

Either method works as part of the method, just swap out dizzy with self. All you need now is a means of choosing what version you call. Perhaps pick a random one:

import random

def any_intro(self):
    cls = random.choice(type(self).__mro__[:-1])
    return cls.intro(self)

would use the unbound-method option to pick a class, any class, except for object.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
0

Somehow you should specify which one you wanna use. Pass it as an argument to intro method. You can do something like this for Puppy class

def intro(self, parent):
    if(parent == 2):
        super(Animal, self).intro()
    elif(parent == 1):
        super(Dog, self).intro()
    else:
        return "I am a puppy named %s" %self.name

Also you can directly call the grandfather method:

Animal.intro(self)
Mehran Meidani
  • 341
  • 1
  • 13