chris from local group
chris from local group

Reputation: 357

Python class inside subclass inheriting from class inside parent class

The title is pretty much self explanatory, but I think this is better explained with an example.

class Dog():

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

    def get_name(self):
        return self.name

    def get_color(self):
        return body_color()

    class personality_1():

        def get_happiness(self):
            return happiness_with_owner()

        def get_sadness(self):
            return sadness()
        ## A lot more personality methods here


class SocialDog(Dog):

    # Override regular method
    def get_color(self):
        return face_color()

    # I want to override the personality 1 class but not completely, just one method
    class personality_2(>>>How to inherit from personality_1?<<<):
        # Now, I would like to override just one method of personality 1:
        def get_happiness(self):
        return happiness_with_others()

Hopefully the logic is correct. I was trying to use super() with no success. Hopefully I can find a solution without using an explicit call to the parent class.

Any thoughts?

Thanks in advance!

Upvotes: 1

Views: 2908

Answers (2)

Kevin J. Chase
Kevin J. Chase

Reputation: 3956

Use the name of the outer class to reach the inner class:

class SocialDog(Dog):
    class personality_2(Dog.personality_1):
        # ...

That said, this is a very weird thing you're doing, hiding the personality classes inside the dog classes, then using them outside...

If a personality is that tightly coupled to a specific class like Dog or SocialDog, what makes personality_2 think it's safe to mess with the behaviour of personality_1? In fact, the personality methods should probably be Dog or SocialDog methods instead.

Or, if it doesn't really matter which dog gets which personality, why not leave the personality classes up at the module level, where they can be instantiated and inherited like any other class? Your various Dog-derived classes would then take an optional personality argument when created:

class WolfPersonality(DogPersonality):
    # ...

class Wolf(Dog):
    def __init__(self, personality=None):
        if personality is None:
            personality = WolfPersonality()
        self.personality = personality
        # ...

# Later...
wolf = Wolf()
wolf_puppy = Wolf(FriendlyDogPersonality())

Upvotes: 1

Sam
Sam

Reputation: 1206

To inherit from the class you specified, according to the code you provided, all that is required is to define the class personality_2 like this:

class SocialDog(Dog):
  #...
    class personality_2(Dog.personality_1):
      #...

Now, as for your problem when trying to use super(), this might be because your base classes of Dog and Dog.personality_1 do not inherit from the python default class object which is required in order to use the super() method. See this answer for details. If that is what you are after, all you need to do is modify your class declarations for Dog and Dog.personality_1 (or whatever they ultimately derive from) to the following:

class Dog(object):
  #...
  class personality_1(object):
    #...

Then you can treat SocialDog.personality_2 just like any other subclass. If you are using python 2, remember when using super() that you need to use the fully qualified name:

super(SocialDog.personality_2, self).super_class_method()
super(SocialDog.personality_2, self).super_class_field

Upvotes: 2

Related Questions