GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing python-course.eu — 12. Multiple Inheritance: Example | OOP | python-course.eu 12. Multiple Inheritance: ExampleBy Bernd Klein. Last modified: 24 Mar 2024. On this page ➤ Robot ClassesThis chapter of our tutorial is meant to deepen the understanding of multiple inheritance that the reader has built up in our previous chapter. We will provide a further extentive example for this important object oriented principle of the programming language Python. We will use a variation of our Robot class as the superclass. We will also summarize some other important aspects of object orientation with Python like properties. We will also work out the differences between overwriting, overloading and overriding. This example has grown during my onsite Python training classes, because I urgently needed simple and easy to understand examples of subclassing and above all one for multiple inheritance. Starting from the superclass Finally we will define a 'combination' of both the Let us start with our By providing an The robots will 'come to live' with a random value between 0 and 1 for the attribute import random class Robot(): __illegal_names = {"Henry", "Oscar"} __crucial_health_level = 0.6 def __init__(self, name): self.name = name #---> property setter self.health_level = random.random() @property def name(self): return self.__name @name.setter def name(self, name): if name in Robot.__illegal_names: self.__name = "Marvin" else: self.__name = name def __str__(self): return self.name + ", Robot" def __add__(self, other): first = self.name.split("-")[0] second = other.name.split("-")[0] return Robot(first + "-" + second) def needs_a_nurse(self): if self.health_level < Robot.__crucial_health_level: return True else: return False def say_hi(self): print("Hi, I am " + self.name) print("My health level is: " + str(self.health_level)) We can test the newly designed first_generation = (Robot("Marvin"), Robot("Enigma-Alan"), Robot("Charles-Henry")) gen1 = first_generation # used as an abbreviation babies = [gen1[0] + gen1[1], gen1[1] + gen1[2]] babies.append(babies[0] + babies[1]) for baby in babies: baby.say_hi() OUTPUT:Hi, I am Marvin-Enigma My health level is: 0.8046874938358127 Hi, I am Enigma-Charles My health level is: 0.9068055696667927 Hi, I am Marvin-Enigma My health level is: 0.9452000668967779 Live Python training See our Python training courses Subclass NursingRobotWe are ready now for subclassing the class NursingRobot(Robot): def __init__(self, name="Hubert", healing_power=None): super().__init__(name) if healing_power is None: self.healing_power = random.uniform(0.8, 1) else: self.healing_power = healing_power def say_hi(self): print("Well, well, everything will be fine ... " + self.name + " takes care of you!") def say_hi_to_doc(self): Robot.say_hi(self) def heal(self, robo): if robo.health_level > self.healing_power: print(self.name + " not strong enough to heal " + robo.name) else: robo.health_level = random.uniform(robo.health_level, self.healing_power) print(robo.name + " has been healed by " + self.name + "!") Let's heal the robot class instances which we created so far. If you look at the code, you may wonder about the function from itertools import chain nurses = [NursingRobot("Hubert"), NursingRobot("Emma", healing_power=1)] for nurse in nurses: print("Healing power of " + nurse.name, nurse.healing_power) print("\nLet's start the healing") for robo in chain(first_generation, babies): robo.say_hi() if robo.needs_a_nurse(): # choose randomly a nurse: nurse = random.choice(nurses) nurse.heal(robo) print("New health level: ", robo.health_level) else: print(robo.name + " is healthy enough!") print() OUTPUT:Healing power of Hubert 0.8505907920868895 Healing power of Emma 1 Let's start the healing Hi, I am Marvin My health level is: 0.2729220195471842 Marvin has been healed by Hubert! New health level: 0.49873537992710615 Hi, I am Enigma-Alan My health level is: 0.5781206628493454 Enigma-Alan has been healed by Emma! New health level: 0.7543798686704403 Hi, I am Charles-Henry My health level is: 0.04402336625130754 Charles-Henry has been healed by Hubert! New health level: 0.5346093674217587 Hi, I am Marvin-Enigma My health level is: 0.8046874938358127 Marvin-Enigma is healthy enough! Hi, I am Enigma-Charles My health level is: 0.9068055696667927 Enigma-Charles is healthy enough! Hi, I am Marvin-Enigma My health level is: 0.9452000668967779 Marvin-Enigma is healthy enough! An interesting question is, what would happen, if Hubert and Emma get added. The question is, what the resulting type will be: x = nurses[0] + nurses[1] x.say_hi() print(type(x)) OUTPUT:Hi, I am Hubert-Emma My health level is: 0.37433207234817967 <class '__main__.Robot'> We see that the result of addition of two nursing robots is a plain robot of type
This is also bad design, because it is mainly a copy the original function with the only exception of creating an instance of NursingRobot instead of a Robot instance.
An elegant solution would be having import random class Robot(): __illegal_names = {"Henry", "Oscar"} __crucial_health_level = 0.6 def __init__(self, name): self.name = name #---> property setter self.health_level = random.random() @property def name(self): return self.__name @name.setter def name(self, name): if name in Robot.__illegal_names: self.__name = "Marvin" else: self.__name = name def __str__(self): return self.name + ", Robot" def __add__(self, other): first = self.name.split("-")[0] second = other.name.split("-")[0] return type(self)(first + "-" + second) def needs_a_nurse(self): if self.health_level < Robot.__crucial_health_level: return True else: return False def say_hi(self): print("Hi, I am " + self.name) print("My health level is: " + str(self.health_level)) class NursingRobot(Robot): def __init__(self, name="Hubert", healing_power=None): super().__init__(name) if healing_power: self.healing_power = healing_power else: self.healing_power = random.uniform(0.8, 1) def say_hi(self): print("Well, well, everything will be fine ... " + self.name + " takes care of you!") def say_hi_to_doc(self): Robot.say_hi(self) def heal(self, robo): if robo.health_level > self.healing_power: print(self.name + " not strong enough to heal " + robo.name) else: robo.health_level = random.uniform(robo.health_level, self.healing_power) print(robo.name + " has been healed by " + self.name + "!") Subclass FightingRobotUnfortunately, our virtual robot world is not better than their human counterpart. In other words, there will be some fighting going on as well. We subclass class FightingRobot(Robot): __maximum_damage = 0.2 def __init__(self, name="Hubert", fighting_power=None): super().__init__(name) if fighting_power: self.fighting_power = fighting_power else: max_dam = FightingRobot.__maximum_damage self.fighting_power = random.uniform(max_dam, 1) def say_hi(self): print("I am the terrible ... " + self.name) def attack(self, other): other.health_level = \ other.health_level * self.fighting_power if isinstance(other, FightingRobot): # the other robot fights back self.health_level = \ self.health_level * other.fighting_power Let us see now, how the fighting works: fighters = (FightingRobot("Rambo", 0.4), FightingRobot("Terminator", 0.2)) for robo in first_generation: print(robo, robo.health_level) fighters[0].attack(robo) print(robo, robo.health_level) OUTPUT:Marvin, Robot 0.49873537992710615 Marvin, Robot 0.19949415197084247 Enigma-Alan, Robot 0.7543798686704403 Enigma-Alan, Robot 0.30175194746817613 Charles-Henry, Robot 0.5346093674217587 Charles-Henry, Robot 0.21384374696870348 What about Rambo fighting Terminator? This spectacular fight can be viewed in the following code: # let us make them healthier first: print("Before the battle:") for fighter in fighters: nurses[1].heal(fighter) print(fighter, fighter.health_level, fighter.fighting_power) fighters[0].attack(fighters[1]) print("\nAfter the battle:") for fighter in fighters: print(fighter, fighter.health_level, fighter.fighting_power) OUTPUT:Before the battle: Rambo has been healed by Emma! Rambo, Robot 0.807864589918383 0.4 Terminator has been healed by Emma! Terminator, Robot 0.7582930215235727 0.2 After the battle: Rambo, Robot 0.1615729179836766 0.4 Terminator, Robot 0.3033172086094291 0.2 An Example of Multiple InheritanceThe underlying idea of the following class class FightingNurseRobot(NursingRobot, FightingRobot): def __init__(self, name, mode="nursing"): super().__init__(name) self.mode = mode # alternatively "fighting" def say_hi(self): if self.mode == "fighting": FightingRobot.say_hi(self) elif self.mode == "nursing": NursingRobot.say_hi(self) else: Robot.say_hi(self) We will instantiate two instances of fn1 = FightingNurseRobot("Donald", mode="fighting") fn2 = FightingNurseRobot("Angela") if fn1.needs_a_nurse(): fn1.heal(fn1) if fn2.needs_a_nurse(): fn2.heal(fn2) print(fn1.health_level, fn2.health_level) fn1.say_hi() fn2.say_hi() fn1.attack(fn2) print(fn1.health_level, fn2.health_level) OUTPUT:0.8892683470807023 0.8699751643457001 I am the terrible ... Donald Well, well, everything will be fine ... Angela takes care of you! 0.5086139994871022 0.23667056868943398 Proper way by Using
|
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |