1

I have a number of different classes with different responsibilities that do not share any methods. But, I want to share some variables that are common amongst all of them. To achieve this goal I have opted for inheritance, which does not seem to work as I had expected it to.

In this question a different method is proposed, but I do not like having to pass all the instances to each constructor.

In the testing I have done so far it seems that each instance of a class instantiates its own superclass instance. Thus, no variables are shared among the classes, but split in the instances.

An MWE to explain:

class Parent:
    def __init__(self):
        self.var1 = None


class Child1(Parent):
    def __init__(self, var1):
        super().__init__()
        self.var1 = var1


class Child2(Parent):
    def __init__(self, var1):
        super().__init__()
        self.var1 = var1


child1 = Child1(1)
child2 = Child2(2)

print(child1.var1)  # prints 1
print(child2.var1)  # prints 2

I am new to python, but it seems I have the wrong understanding. The behavior I was expecting is that both times 2 would be printed, since child2 is instantiated last, thus setting var1=2 for child1 as well.

How do I make the subclasses share the same superclass instance & variables? Do I have to instantiate from the superclass down and not up from the subclasses?

EDIT: Whoops, sorry that I'm a beginner Karl! Guess I'll check out composition then..

7
  • 4
    "In the testing I have done so far it seems that each instance of a class instantiates its own superclass instance." Yes, of course they do. They do in every language that has a concept of classes and inheritance. There is no reason for it to work any other way, because that's the point of inheritance: a derived instance is substitutable for a base instance. "How do I make the subclasses share the same superclass instance & variables? " You can't. That's not what inheritance is for. Use composition. Commented Sep 3, 2021 at 6:43
  • 2
    I don't care if you "don't like having to pass things around". That's one example of explicit is better than implicit. The class used for the common data, used via composition, is still helping you organize the code. Commented Sep 3, 2021 at 6:44
  • 1
    "Do I have to instantiate from the superclass down and not up from the subclasses?" This concept does not make any sense. When you use super, you are not instantiating. You are initializing. The object, including its base, already exists at this point. Commented Sep 3, 2021 at 6:46
  • 1
    Inheritance is precisely to share code, not data. Individual objects hold their individual data. You'd need to make those attributes class attributes instead of instance attributes, but then you may as well use global variables for all the good that does in your case. Commented Sep 3, 2021 at 6:48
  • 1
    The way you want things to work is impossible. You apparently would like, when you create each Child1 or Child2 instance, to use the same existing Parent instance as a base. But they cannot do that because there isn't an existing Parent instance to have in common. You could use per-class rather than per-instance data, but that is harder than just passing things around, and also loses you flexibility (what if you have a Child1 and a Child2 that should share one piece of data, and then a second Child1 and Child2 that should share a different piece?) Commented Sep 3, 2021 at 6:49

1 Answer 1

5

You are mistaking instance variables with class variables. Here, you defined instance variables because the assignation is inside the __init__ (the initialization of the instance).
What you want is to define a class variable, like so :

class Parent:
    var1 = None


class Child1(Parent):
    def __init__(self, var1):
        super().__init__()
        Parent.var1 = var1


class Child2(Parent):
    def __init__(self, var1):
        super().__init__()
        Parent.var1 = var1


child1 = Child1(1)
child2 = Child2(2)

print(child1.var1)  # prints 2 !! <-----
print(child2.var1)  # prints 2

Before, each instance had its own var1 variable, that's what an instance variable is, by definition.

But in my example, the var1 variable is defined into the class object. Each instance can reference it (using Parent.var1), but it is always the same variable. But Python is nice and lets you access class variable as if they were instance variables, which can cause confusion.

But bear in mind that this is not what inheritance is designed for. Yes, you can use that way but it is a bit unuasual.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for actually answering my question! I was just wondering, Child1 and Child2 would not need to inherit from Parent anymore correct? It seems to me that this is a way of creating global variables under a class, as to not pollute the namespace. Is this, as you say, unusual and not what inheritance is designed for because it leads to more implicit (variables from Parent being used behind the scenes) code than explicit (deliberately passing variables to functions/inits that need it)?
@JonasM. Yes, if what you want is simply a shared mutable variable, just declare a variable and it will work the same. But as you noted, it can serve as a namespace : the shared variable belongs to a class, which clearly indicates that it is related to what the class' (sub-)instances do. I recall doing it recently for defining constants relevant only to a hierarchy of classes. But inheritance is more than that : inherited methods, overloading, polymorphism, ... You don't need inheritance to do what you want (try removing Parent and super()s from Child1 and Child2) but is is clearer.
Class attribute Parent.var1 is a static variable and shared in all inherited instances as if it was an instance variable. On the other hand, if there is an instance variable with the same name self.var1 (OP's code case), child1.var1 or child2.var1 will hide the class variable name. One has to explicitly qualify it as Parent.var1 to show.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.