How can a child class inherit a class method from its parent that gets a class variable from the child in python?

Question:

I have a code here where I define a parent class with class methods and class variables:

class Parent:
    var1 = 'foo'
    var2 = 'bar'
    
    def getVar1Var2AsString(self):
        return f'{Parent.getVar1()}_{Parent.getVar2()}'

    @classmethod
    def getVar1(cls):
        return cls.var1

    @classmethod
    def getVar2(cls):
        return cls.var2

And then, I have a code where I define the child class:

class Child(Parent):
    var1 = 'banana'
    var2 = 'apple'

And then I run:

child = Child()
output = child.getVar1Var2AsString()
print(output)

I expected that the output would return banana_apple, but it returns foo_bar instead.

How can I get the result I expect? I’m kind of new in OOP.

Asked By: caio.valente14

||

Answers:

In getVar1Var2AsString, when you call Parent.getVar1(), you do so without any reference to the current object or its class. It always looks up the methods on Parent. If you want to look up the methods in the current object’s class, use self.getVar1(). You also don’t need the getter methods at all, you can just use self.var1 and self.var2.

Answered By: Blckknght

The inheritance is fine, it’s the variable access that’s wrong. In getVar1Var2AsString, when you write Parent, that always refers to Parent (of course), not the class of self, which can be got with type(self). Or if you’d rather look up the class variables on the instance, just use self.

By the way, I don’t think the getters add anything here.

So:

def getVar1Var2AsString(self):
    return f'{type(self).var1}_{type(self).var2}'

Or, since self is only being used to look up its class, you could make it a class method:

@classmethod
def getVar1Var2AsString(cls):
    return f'{cls.var1}_{cls.var2}'

To be clear, it looks like you thought cls in a classmethod would take the value of type(self), but that’s not the case.

Answered By: wjandrea

In case you want to get foo_bar in case the object is an instance of the Parent class and banana_apple in case it’s an instance of the Child class you can do this by changing your getVar1Var2AsString to

@classmethod
def getVar1Var2AsString(cls):
    return f"{cls.getVar1()}_{cls.getVar2()}"

This way the values of the corresponding class are used to generate the output.

Answered By: Jonas