Charlie Morton
Charlie Morton

Reputation: 787

Python inner class inherit from outer

I have an issue with class inheritence and haven't been able to find an appropriate solution elsewhere.

I have 2 classes a Parent class and a Child class.

A Child is a type of Human so I want to use class inheritance, which normally would be straightforward we just have.

class Human:
    def __init__(self,type,name):     # Do this when we create a Node instance
        self.type = type
        self.name = name

class Child(Human):
    def __init__(self,name,siblings):     # Do this when we create a Node instance
        super().__init__(type=Child,name=name)
        self.siblings = siblings

but I want to be a pain and I want to create instances by using Human.Child(parameters) rather than Child(parameters) and I don't want to have a Child class in the main scope.

I have managed to make that work by using a classmethod but it's pretty messy. Is there a more elegant solution?

class Human:
    def __init__(self,type,name):     # Do this when we create a Node instance
        self.type = type
        self.name = name

    def execute(self):
        print(f"executing the Human {self.name}")


    @classmethod
    def Child(cls,*args,**kwargs):

        class Child(cls):
            def __init__(self,name,siblings):
                super().__init__(type=Child,name=name)
                self.siblings = siblings

            def execute(self):
                print(f"executing the Child {self.name}")

        return(Child(*args,**kwargs))

ideally it would look something like below, but of course, we cannot pass Human to the Child class as it hasn't yet been defined.

class Human:
    def __init__(self,type,name):     # Do this when we create a Node instance
        self.type = type
        self.name = name

    def execute(self):
        print(f"executing the Human {self.name}")


    class Child(Human):
        def __init__(self,name,siblings):
            super().__init__(type=Child,name=name)
            self.siblings = siblings

        def execute(self):
            print(f"executing the Child {self.name}")

Upvotes: 1

Views: 261

Answers (1)

Mad Physicist
Mad Physicist

Reputation: 114320

When a class definition is encountered, the class object isn't created until the entire body is read, and a full dictionary accumulated. This is the opposite of how a module object is created, where an empty module is available immediately to help avoid circular imports, among other things. That being said, nothing prevents you from modifying the attributes of a class after it is fully created.

class Human:
    def __init__(self,type,name):     # Do this when we create a Node instance
        self.type = type
        self.name = name

class Child(Human):
    def __init__(self,name,siblings):     # Do this when we create a Node instance
        super().__init__(type=Child,name=name)
        self.siblings = siblings

Human.Child = Child
del Child

A few things to keep in mind:

  1. Passing in type is redundant. You can always access that information through the type function.
  2. Humans tend to have siblings even after they stop being children.
  3. While I'm the one suggesting this approach, I do not endorse it. Rather than complicating things without any need, try to keep your classes in the top level namespace.

Upvotes: 4

Related Questions