简体   繁体   中英

How to inherit from 2 classes without having to change the original classes?

Whenever I run this code I always get a TypeError that says __init__() missing 1 required positional argument: 'hours' , but I am not trying to change anything from the original class that the ScientificSwimmer class is inheriting from…if that makes sense.

Here is the code:

class Human:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def hobby(self):
        print("Likes watching Netflix")

    def info(self):
        print(self.name , "is ",self.age," years old")


class Scientist(Human):
    def __init__(self, name, age, lab):
        super().__init__(name, age)
        self.lab = lab

    def hobby(self):
        print("Likes doing scientific experiments")

    def labName(self,lab):
        print("works at the " ,lab, "laboratory")


class Swimmer(Human):
    def __init__(self, name, age, hours):
        super().__init__(name,age)
        self.hours = hours

    def hobby(self):
        print("likes swimmming in the lake" )

    def hoursSwimming(self, hours):
        print("swims ", hours , "hours per week")


class ScientificSwimmer(Scientist, Swimmer):

    def __init__ (self, name, age, lab, hours):
       Scientist.__init__(self,name, age, lab)
       Swimmer.__init__(self, name, age, hours)


scienswim = ScientificSwimmer("\nJohn Smith", 30, "nuclear", 100)
scienswim.info()
scienswim.hobby()
scienswim.labName("nuclear")
scienswim.hoursSwimming(100)

My desired result is for it to print:

John smith is 30 years old.
likes doing scientific experiments.
works at the nuclear laboratory.
swims 100 hours per week.

Your original classes simply aren't designed correctly to support cooperative inheritance, which is what super is designed for. The number one rule for using super is this: you can't assume you know which class super() will refer to. That's determined by the runtime type of self , not the classes you statically inherit from.

Use keyword arguments exclusively to ensure that the method signatures remain compatible, and always call super().__init__ with any unknown keyword arguments (namely, those not explicitly mentioned in the signature).

class Human: 
    def __init__(self, *, name, age, **kwargs):
        super().__init__(**kwargs)
        self.name = name
        self.age = age
        
    def hobby(self):
        print("Likes watching Netflix")
        
    def info(self):
        print(self.name , "is ",self.age," years old")
        

class Scientist(Human): 
    def __init__(self, *, lab, **kwargs):
        super().__init__(**kwargs)
        self.lab = lab
        
    def hobby(self):
        print("Likes doing scientific experiments")
    
    def labName(self):
        print("works at the " , self.lab, "laboratory")
  

class Swimmer(Human):
    def __init__(self, *, hours, **kwargs):
        super().__init__(**kwargs)
        self.hours = hours
    
    def hobby(self):
        print("likes swimmming in the lake" )
    
    def hoursSwimming(self):
        print("swims ", self.hours , "hours per week")
     

class ScientificSwimmer(Scientist, Swimmer):
    pass


scienswim = ScientificSwimmer(name="John Smith", age=30, lab="nuclear", hours=100)
scienswim.info()
scienswim.hobby()
scienswim.labName()
scienswim.hoursSwimming()

The method resolution order for ScientificSwimmer is [ScientificSwimmer, Scientist, Swimmer, Human, object] . This results in the following:

  1. ScientificSwimmer need not be defined, as the other __init__ methods will take care of everything.
  2. Scientist.__init__ extracts the lab keyword argument and passes the rest on to the next class.
  3. Swimmer.__init__ extracts the hours keyword argument and passes the rest on to the next class.
  4. Human.__init__ extracts the name and age keyword arguments and passes the rest on to the next class.
  5. object.__init__ receives no keyword arguments, all defined arguments having been correctly extracted by downstream classes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM