Skip to content

Commit 0862949

Browse files
restructure
1 parent 17fad31 commit 0862949

9 files changed

Lines changed: 877 additions & 1581 deletions

File tree

book/python/oop/Inheritance.ipynb

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Inheritance\n",
8+
"\n",
9+
"Another of the most important goals of the object-oriented approach to programming is the creation of stable, reliable, reusable code. If you had to create a new class for every kind of object you wanted to model, you would hardly have any reusable code. In Python and any other language that supports OOP, one class can **inherit** from another class. This means you can base a new class on an existing class; the new class *inherits* all of the attributes and behavior of the class it is based on. A new class can override any undesirable attributes or behavior of the class it inherits from, and it can add any new attributes or behavior that are appropriate. The original class is called the **parent** class or **superclass**, and the new class is a **child** or **subclass** of the parent class.\n",
10+
"\n",
11+
"The child class inherits all attributes and behavior from the parent class, but any attributes that are defined in the child class are not available to the parent class. This may be obvious to many people, but it is worth stating. This also means a child class can ***override*** behavior of the parent class. If a child class defines a method that also appears in the parent class, objects of the child class will use the new method rather than the parent class method.\n",
12+
"\n",
13+
"To better understand inheritance, let's look at an example of a class that can be based on the Rocket class."
14+
]
15+
},
16+
{
17+
"cell_type": "markdown",
18+
"metadata": {},
19+
"source": [
20+
"## The Shuttle class\n",
21+
"\n",
22+
"If you wanted to model a space shuttle, you could write an entirely new class. But a space shuttle is just a special kind of rocket. Instead of writing an entirely new class, you can inherit all of the attributes and behavior of a Rocket, and then add a few appropriate attributes and behavior for a Shuttle.\n",
23+
"\n",
24+
"One of the most significant characteristics of a space shuttle is that it can be reused. So the only difference we will add at this point is to record the number of flights the shutttle has completed. Everything else you need to know about a shuttle has already been coded into the Rocket class.\n",
25+
"\n",
26+
"Here is what the Shuttle class looks like:"
27+
]
28+
},
29+
{
30+
"cell_type": "code",
31+
"execution_count": 1,
32+
"metadata": {},
33+
"outputs": [
34+
{
35+
"name": "stdout",
36+
"output_type": "stream",
37+
"text": [
38+
"10\n"
39+
]
40+
}
41+
],
42+
"source": [
43+
"from rocket import Rocket #import original Rocket class from a py file\n",
44+
"\n",
45+
"class Shuttle(Rocket):\n",
46+
" # Shuttle simulates a space shuttle, which is really\n",
47+
" # just a reusable rocket.\n",
48+
" \n",
49+
" def __init__(self, x=0, y=0, flights_completed=0):\n",
50+
" super().__init__(x, y)\n",
51+
" self.flights_completed = flights_completed\n",
52+
" \n",
53+
"shuttle = Shuttle(10,0,3)\n",
54+
"print(shuttle.x)"
55+
]
56+
},
57+
{
58+
"cell_type": "markdown",
59+
"metadata": {},
60+
"source": [
61+
"When a new class is based on an existing class, you write the name of the parent class in parentheses when you define the new class:\n",
62+
"```python\n",
63+
"class NewClass(ParentClass):\n",
64+
"```"
65+
]
66+
},
67+
{
68+
"cell_type": "markdown",
69+
"metadata": {},
70+
"source": [
71+
"The `__init__()` function of the new class needs to call the `__init__()` function of the parent class. The `__init__()` function of the new class needs to accept all of the parameters required to build an object from the parent class, and these parameters need to be passed to the `__init__()` function of the parent class. The `super().__init__()` function takes care of this:\n",
72+
"\n",
73+
"```python\n",
74+
"class NewClass(ParentClass):\n",
75+
" \n",
76+
" def __init__(self, arguments_parent_class, arguments_new_class):\n",
77+
" super().__init__(arguments_parent_class)\n",
78+
" # Code for initializing an object of the new class.\n",
79+
"```"
80+
]
81+
},
82+
{
83+
"cell_type": "markdown",
84+
"metadata": {},
85+
"source": [
86+
"The `super()` function passes the *self* argument to the parent class automatically."
87+
]
88+
},
89+
{
90+
"cell_type": "markdown",
91+
"metadata": {},
92+
"source": [
93+
"Inheritance is a powerful feature of object-oriented programming. Using just what you have seen so far about classes, you can model an incredible variety of real-world and virtual phenomena with a high degree of accuracy. The code you write has the potential to be stable and reusable in a variety of applications."
94+
]
95+
}
96+
],
97+
"metadata": {
98+
"kernelspec": {
99+
"display_name": "Python 3",
100+
"language": "python",
101+
"name": "python3"
102+
},
103+
"language_info": {
104+
"codemirror_mode": {
105+
"name": "ipython",
106+
"version": 3
107+
},
108+
"file_extension": ".py",
109+
"mimetype": "text/x-python",
110+
"name": "python",
111+
"nbconvert_exporter": "python",
112+
"pygments_lexer": "ipython3",
113+
"version": "3.12.0"
114+
}
115+
},
116+
"nbformat": 4,
117+
"nbformat_minor": 4
118+
}

book/python/oop/Polymorphism.ipynb

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Polymorphism\n",
8+
"\n",
9+
"Another important goal of the object-oriented approach to programming is to provide flexibility of your code. This can be achived by Polymorphism, which entails that an entity is able to take multiple forms. In Python polymorphism allows us to create methods in a child class with the same name as a method in a parent class. This would mean that a method can serve one purpose in a parent class and different one in a child class.\n",
10+
"\n",
11+
"Child classes inherit all the methods of their parent classes, however, sometimes those methods need to be modified to fit the function of the child. This is achieved by reimplementing the parent methods in the child class.\n",
12+
"\n",
13+
"To better understand polymorphism, let's look at an example of a class that can be based on the Shuttle class and transitively on the Rocket class as well."
14+
]
15+
},
16+
{
17+
"cell_type": "markdown",
18+
"metadata": {},
19+
"source": [
20+
"## The ImprovedShuttle class\n",
21+
"\n",
22+
"Our Shuttle class already improves the basic Rocket class, however, the information we receive from the Rocket class such as `get_distance` is very limited. This is because we currently only get information about the absolute distance, but we do not know the direction, which we need to face to get to that place the fastest.\n",
23+
"\n",
24+
"Therefore, we will create an improved Shuttle, which will be based on the initial Shuttle and will provide better distance information such as angle in which we need to rotate. The formula used is based on taking arctangent of the 2-dimension distances and transforming from radians to degrees.\n",
25+
"\n",
26+
"Here is what the ImprovedShuttle class looks like:"
27+
]
28+
},
29+
{
30+
"cell_type": "code",
31+
"execution_count": 2,
32+
"metadata": {},
33+
"outputs": [
34+
{
35+
"name": "stdout",
36+
"output_type": "stream",
37+
"text": [
38+
"The shuttles are 4.242641 units apart.\n",
39+
"The angle the initial shuttle needs to rotate in case it needs to go to the other shuttle is 45.00 degrees.\n"
40+
]
41+
}
42+
],
43+
"source": [
44+
"from rocket import Shuttle\n",
45+
"\n",
46+
"from math import atan, pi, sqrt\n",
47+
"\n",
48+
"class ImprovedShuttle(Shuttle):\n",
49+
" # Improved Shuttle that provides better distance information\n",
50+
" # such as angle.\n",
51+
" \n",
52+
" def __init__(self, x=0, y=0, flights_completed=0):\n",
53+
" super().__init__(x, y)\n",
54+
" self.flights_completed = flights_completed\n",
55+
" \n",
56+
" def get_distance(self, other_rocket):\n",
57+
" # Calculates the distance from this rocket to another rocket,\n",
58+
" # the angle to rotate to face the other rocket,\n",
59+
" # and returns those values.\n",
60+
" distance = super().get_distance(other_rocket)\n",
61+
" angle = atan((other_rocket.y - self.y) / (other_rocket.x - self.x)) * (180 / pi)\n",
62+
" return distance, angle\n",
63+
" \n",
64+
"improvedShuttle = ImprovedShuttle(10,0,3)\n",
65+
"otherShuttle = ImprovedShuttle(13, 3)\n",
66+
"\n",
67+
"# Show the distance between them.\n",
68+
"distance, angle = improvedShuttle.get_distance(otherShuttle)\n",
69+
"print(f\"The shuttles are {distance:.6f} units apart.\")\n",
70+
"print(f\"The angle the initial shuttle needs to rotate in case it needs to go to the other shuttle is {angle:.2f} degrees.\")"
71+
]
72+
},
73+
{
74+
"cell_type": "markdown",
75+
"metadata": {},
76+
"source": [
77+
"As you can see in the example above, since ImprovedShuttle inherits Shuttle and Shuttle inherits Rocket, then transitively ImprovedShuttle is a child of Rocket class and has access to the parent `get_distance` method. It is possible to access that parent method by making a `super().get_distance()` call.\n",
78+
"\n",
79+
"As a result, class ImprovedShuttle has ***overridden*** Rocket's get_distance. This means that it has reimplemented the parent's method.\n",
80+
"\n",
81+
"It is important to mention that it is not necessary to override (reimplement) every method in the parent class when using inheritance, but if needed, it is possible. \n",
82+
"\n",
83+
":::{note}\n",
84+
"ImprovedShuttle's get_distance() now returns two outputs, while the parent class only returns one. Imagine you are looping a list containing a mix of Rockets and ImprovedShuttles to store their distance in an array (with as many elements as the length of the lists); this difference in the output may require some extra lines of code to handle potential problems.\n",
85+
":::"
86+
]
87+
}
88+
],
89+
"metadata": {
90+
"kernelspec": {
91+
"display_name": "Python 3",
92+
"language": "python",
93+
"name": "python3"
94+
},
95+
"language_info": {
96+
"codemirror_mode": {
97+
"name": "ipython",
98+
"version": 3
99+
},
100+
"file_extension": ".py",
101+
"mimetype": "text/x-python",
102+
"name": "python",
103+
"nbconvert_exporter": "python",
104+
"pygments_lexer": "ipython3",
105+
"version": "3.12.0"
106+
}
107+
},
108+
"nbformat": 4,
109+
"nbformat_minor": 4
110+
}

0 commit comments

Comments
 (0)