Home > Blockchain >  inheritance in python about derived class usage syntax
inheritance in python about derived class usage syntax

Time:05-25

I have the following code:

class person:
    def __init__(self,fname,lname):
        self.fname=fname
        self.lname=lname
    
    def printper(self):
        return self.fname,self.lname

class emp:
    def __init__(self,fname,lname,empno):
        self.empno=empno
        person.__init__(self,fname,lname)
    
    def printper(self):
        return self.empno,self.fname,self.lname

e1=emp("john","michael",20)
print(e1.printper())

# output: (20, 'john', 'michael')

I am confused - emp does not inherit from person, but the code still works. Why? Calling person.__init__() in the emp.__init__() seems to make the code work. Is that all that is necessary? Is it not actually mandatory to write class emp(person): to have a derived class?

CodePudding user response:

Python does not care about checking types, inheritance relationships, etc. ahead of time. It only cares what happens when the code is run. This allows for what is called "duck typing":

class Employee:
    def fired(self):
        print("Oh no, I have to look for a new job")

class Gun:
    def fired(self):
        print("Bang! Did the bullet hit the target?")

for thing in [Employee(), Gun()]:
    thing.fired()

It does not matter that the classes Employee and Gun have nothing to do with each other, and it does not matter that the purpose of fired is completely different. Both of the objects in the list have a method that is named fired, so the code works without error.

Similarly in your code:

class emp:
    def __init__(self,fname,lname,empno):
        self.empno=empno
        person.__init__(self,fname,lname)

If we call person.__init__, then that is just a function that we found inside the person class - not a method that we looked up on an object. This is because we used a class on the left-hand side of ., not an instance. That function will happily accept an emp instance as the value for self - it does not care whether that self is a person instance. It's a user-defined object, so there is no problem setting fname and lname attributes.

After that, the printper method will have no problem finding fname and lname attributes on the emp instance - because they are there.

"So why bother ever inheriting at all, then?"

Because even though this "works", it still doesn't actually make an inheritance relationship. That has some consequences:

  • super does not work - the __init__ call had to say explicitly what other class to use, and the code doesn't really make sense. From an outside perspective, it's sheer coincidence that it sets the right attributes.

  • isinstance will not work, by default. emp is not in the __bases__, nor the __mro__ of person.

  • Related