{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# HyperLearning AI - Introduction to Python\n",
"An introductory course to the Python 3 programming language, with a curriculum aligned to the Certified Associate in Python Programming (PCAP) examination syllabus (PCAP-31-02).
\n",
"https://knowledgebase.hyperlearning.ai/courses/introduction-to-python\n",
"\n",
"\n",
"## 08. Classes and Objects Part 1\n",
"https://knowledgebase.hyperlearning.ai/en/courses/introduction-to-python/modules/8/classes-and-objects-part-1\n",
"\n",
"In this module we will introduce the object oriented programming (OOP) paradigm - a means to model the world and our software applications as objects that interact with each other. Supported by hands-on examples in Python, we will explore the fundamental concepts in object oriented programming, including:\n",
"\n",
"* **Classes** - classes, superclasses, subclasses, inheritance, and creating objects\n",
"* **Class Attributes** - class variables, instance variables, managing attributes and explicit constructor invocation\n",
"* **Class Methods** - defining and using class methods, the self parameter, the init method and the str method\n",
"* **Inheritance** - inheritance, overriding, single inheritance and multiple inheritance\n",
"* **Constructors** - writing and using constructors\n",
"* **Introspection** - dict, name, module and bases properties, and examining class structure"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. Programming Paradigms\n",
"#### 1.1. Imperative Programming"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The sum of the numbers in [1, 2, 3, 4, 5] is: 15\n"
]
}
],
"source": [
"# Write a program using imperative programming to calculate the sum of a given list of numbers\n",
"sum = 0\n",
"my_numbers = [1, 2, 3, 4, 5]\n",
"for number in my_numbers:\n",
" sum += number\n",
"print(f'The sum of the numbers in {my_numbers} is: {sum}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 1.2. Functional Programming"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"15\n",
"15\n"
]
}
],
"source": [
"from functools import reduce\n",
"\n",
"# Write a program using functional programming to calculate the sum of a given list of numbers\n",
"def add(x, y):\n",
" return x + y\n",
"sum = reduce(add, my_numbers)\n",
"print(sum)\n",
"\n",
"# Write a program using functional programming and a lambda function to calculate the sum of a given list of numbers\n",
"sum = reduce(lambda x, y: x + y, my_numbers)\n",
"print(sum)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. OOP Fundamentals\n",
"#### 2.2.1. Creating Objects"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"# Update sys.path so that it can find our example module\n",
"import sys\n",
"sys.path.append('examples/formulapy')"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"# Import our example module containing our Car class definition\n",
"from example import Car"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"ename": "TypeError",
"evalue": "__init__() missing 8 required positional arguments: 'number_doors', 'registration_number', 'make', 'model', 'year_manufactured', 'maximum_speed', 'acceleration_rate', and 'deceleration_rate'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Try to create a new car object without the required arguments\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mmy_car\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mCar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m: __init__() missing 8 required positional arguments: 'number_doors', 'registration_number', 'make', 'model', 'year_manufactured', 'maximum_speed', 'acceleration_rate', and 'deceleration_rate'"
]
}
],
"source": [
"# Try to create a new car object without the required arguments\n",
"my_car = Car()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Car{'number_doors': 0, 'registration_number': 'MERC 123', 'make': 'Mercedes', 'model': 'AMG F1 W10 EQ Power+', 'year_manufactured': 2019, 'maximum_speed': 200, 'acceleration_rate': 20, 'deceleration_rate': 50, 'mileage_miles': 0, 'speed_mph': 0}\n",
"Car{'number_doors': 0, 'registration_number': 'MON 888', 'make': 'Ferrari', 'model': 'SF1000', 'year_manufactured': 2020, 'maximum_speed': 200, 'acceleration_rate': 15, 'deceleration_rate': 60, 'mileage_miles': 0, 'speed_mph': 0}\n"
]
}
],
"source": [
"# Create a new car object\n",
"mercedes_f1 = Car(number_doors = 0,\n",
" registration_number = 'MERC 123',\n",
" make = 'Mercedes',\n",
" model = 'AMG F1 W10 EQ Power+',\n",
" year_manufactured = 2019,\n",
" maximum_speed = 200,\n",
" acceleration_rate = 20,\n",
" deceleration_rate = 50)\n",
"\n",
"# Print the type of object that this is i.e. the class that was used to instantiate this object\n",
"print(type(mercedes_f1))\n",
"\n",
"# Print a string representation of the car object\n",
"print(mercedes_f1)\n",
"\n",
"# Create another new car object\n",
"ferrari_f1 = Car(number_doors = 0,\n",
" registration_number = 'MON 888',\n",
" make = 'Ferrari',\n",
" model = 'SF1000',\n",
" year_manufactured = 2020,\n",
" maximum_speed = 200,\n",
" acceleration_rate = 15,\n",
" deceleration_rate = 60)\n",
"\n",
"# Print a string representation of the car object\n",
"print(ferrari_f1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.2.2. Accessing Attributes"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"200\n",
"MON 888\n"
]
}
],
"source": [
"# Access and display the maximum speed of the Mercedes car object\n",
"print(mercedes_f1.maximum_speed)\n",
"\n",
"# Access and display the registration number of the Ferrari car object\n",
"print(ferrari_f1.registration_number)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.2.3. Modifying Attributes"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Car{'number_doors': 0, 'registration_number': 'MERC 123', 'make': 'Mercedes', 'model': 'AMG F1 W10 EQ Power+', 'year_manufactured': 2019, 'maximum_speed': 220, 'acceleration_rate': 20, 'deceleration_rate': 50, 'mileage_miles': 0, 'speed_mph': 0}\n",
"Car{'number_doors': 0, 'registration_number': 'SCUD 888', 'make': 'Ferrari', 'model': 'SF1000', 'year_manufactured': 2020, 'maximum_speed': 200, 'acceleration_rate': 15, 'deceleration_rate': 60, 'mileage_miles': 0, 'speed_mph': 0}\n"
]
}
],
"source": [
"# Modify the maximum speed of the Mercedes car object\n",
"mercedes_f1.maximum_speed = 220\n",
"print(mercedes_f1)\n",
"\n",
"# Modify the registration number of the Ferrari car object\n",
"ferrari_f1.registration_number = 'SCUD 888'\n",
"print(ferrari_f1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.2.4. Deleting Attributes"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Car{'number_doors': 0, 'registration_number': 'MERC 123', 'make': 'Mercedes', 'model': 'AMG F1 W10 EQ Power+', 'year_manufactured': 2019, 'maximum_speed': 220, 'acceleration_rate': 20, 'deceleration_rate': 50, 'mileage_miles': 0, 'speed_mph': 0}\n",
"0\n",
"Car{'registration_number': 'MERC 123', 'make': 'Mercedes', 'model': 'AMG F1 W10 EQ Power+', 'year_manufactured': 2019, 'maximum_speed': 220, 'acceleration_rate': 20, 'deceleration_rate': 50, 'mileage_miles': 0, 'speed_mph': 0}\n"
]
},
{
"ename": "AttributeError",
"evalue": "'Car' object has no attribute 'number_doors'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mmercedes_f1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumber_doors\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmercedes_f1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmercedes_f1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumber_doors\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m: 'Car' object has no attribute 'number_doors'"
]
}
],
"source": [
"# Delete the number of doors attribute belonging to the Mercedes car object\n",
"print(mercedes_f1)\n",
"print(mercedes_f1.number_doors)\n",
"del mercedes_f1.number_doors\n",
"print(mercedes_f1)\n",
"print(mercedes_f1.number_doors)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.2.5. Deleting Objects"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Car{'number_doors': 0, 'registration_number': 'RB 999', 'make': 'Red Bull', 'model': 'RB9', 'year_manufactured': 2013, 'maximum_speed': 210, 'acceleration_rate': 18, 'deceleration_rate': 60, 'mileage_miles': 0, 'speed_mph': 0}\n"
]
}
],
"source": [
"# Create a new car object\n",
"redbull_f1 = Car(number_doors = 0,\n",
" registration_number = 'RB 999',\n",
" make = 'Red Bull',\n",
" model = 'RB9',\n",
" year_manufactured = 2013,\n",
" maximum_speed = 210,\n",
" acceleration_rate = 18,\n",
" deceleration_rate = 60)\n",
"\n",
"# Print a string representation of the car object\n",
"print(redbull_f1)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'redbull_f1' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;31m# Try to print a string representation of the deleted car object\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mredbull_f1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mNameError\u001b[0m: name 'redbull_f1' is not defined"
]
}
],
"source": [
"# Delete the previously created car object\n",
"del redbull_f1\n",
"\n",
"# Try to print a string representation of the deleted car object\n",
"print(redbull_f1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.2.6. Introspection"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'registration_number': 'MERC 123', 'make': 'Mercedes', 'model': 'AMG F1 W10 EQ Power+', 'year_manufactured': 2019, 'maximum_speed': 220, 'acceleration_rate': 20, 'deceleration_rate': 50, 'mileage_miles': 0, 'speed_mph': 0}\n"
]
}
],
"source": [
"# Access an object's attribute references\n",
"print(mercedes_f1.__dict__)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Car\n",
"\n",
"Car\n"
]
}
],
"source": [
"# Access a class's name\n",
"print(Car.__name__)\n",
"\n",
"# Access an object's class name (or type name) from which it was instantiated\n",
"print(mercedes_f1.__class__)\n",
"print(mercedes_f1.__class__.__name__)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"example\n",
"example\n"
]
}
],
"source": [
"# Access the name of the module that a class was defined in\n",
"print(Car.__module__)\n",
"print(mercedes_f1.__class__.__module__)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(,)\n",
"(,)\n"
]
}
],
"source": [
"# Access a class's base classes\n",
"print(Car.__bases__)\n",
"print(mercedes_f1.__class__.__bases__)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.2.7. Adding Attributes"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Car{'registration_number': 'MERC 123', 'make': 'Mercedes', 'model': 'AMG F1 W10 EQ Power+', 'year_manufactured': 2019, 'maximum_speed': 220, 'acceleration_rate': 20, 'deceleration_rate': 50, 'mileage_miles': 0, 'speed_mph': 0}\n",
"Car{'registration_number': 'MERC 123', 'make': 'Mercedes', 'model': 'AMG F1 W10 EQ Power+', 'year_manufactured': 2019, 'maximum_speed': 220, 'acceleration_rate': 20, 'deceleration_rate': 50, 'mileage_miles': 0, 'speed_mph': 0, 'height_mm': 950, 'width_mm': 2000, 'weight_kg': 743, 'power_kw': 750}\n"
]
}
],
"source": [
"# Add a completely new attribute to one of our car objects that was not defined in the Car class definition\n",
"print(mercedes_f1)\n",
"setattr(mercedes_f1, 'height_mm', 950)\n",
"setattr(mercedes_f1, 'width_mm', 2000)\n",
"setattr(mercedes_f1, 'weight_kg', 743)\n",
"setattr(mercedes_f1, 'power_kw', 750)\n",
"print(mercedes_f1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.2.8. Invoking Methods"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"23/08/2020 21:01:21: Ferrari SF1000 current speed: 0mph\n",
"23/08/2020 21:01:22: Ferrari SF1000 current speed: 15mph\n",
"23/08/2020 21:01:23: Ferrari SF1000 current speed: 30mph\n",
"23/08/2020 21:01:24: Ferrari SF1000 current speed: 45mph\n",
"23/08/2020 21:01:25: Ferrari SF1000 current speed: 60mph\n",
"23/08/2020 21:01:26: Ferrari SF1000 current speed: 75mph\n",
"23/08/2020 21:01:27: Ferrari SF1000 current speed: 90mph\n",
"23/08/2020 21:01:28: Ferrari SF1000 current speed: 105mph\n",
"23/08/2020 21:01:29: Ferrari SF1000 current speed: 120mph\n",
"23/08/2020 21:01:30: Ferrari SF1000 current speed: 135mph\n",
"23/08/2020 21:01:31: Ferrari SF1000 current speed: 150mph\n",
"23/08/2020 21:01:32: Ferrari SF1000 current speed: 165mph\n",
"23/08/2020 21:01:33: Ferrari SF1000 current speed: 180mph\n",
"23/08/2020 21:01:34: Ferrari SF1000 current speed: 195mph\n",
"23/08/2020 21:01:35: Ferrari SF1000 current speed: 200mph\n"
]
}
],
"source": [
"# Invoke the Car.accelerate() method on an existing car object\n",
"ferrari_f1.accelerate()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.3. Inheritance\n",
"#### 2.3.3. Super Function"
]
},
{
"cell_type": "code",
"execution_count": 117,
"metadata": {},
"outputs": [],
"source": [
"# Update sys.path so that it can find our formulapy module\n",
"import sys\n",
"sys.path.append('examples/formulapy')\n",
"\n",
"# Import our new vehicle domain data model module\n",
"from model import Aircraft, Car, RoadVehicle, Vehicle"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Car{'number_engines': 1, 'engine_horsepower_kw': 673, 'chassis_height_mm': 1188, 'chassis_width_mm': 1946, 'chassis_depth_mm': 4588, 'make': 'McLaren', 'model': 'P1', 'year_manufactured': 2013, 'maximum_speed_mph': 217, 'acceleration_rate_mps': 20, 'deceleration_rate_mps': 50, 'mileage_miles': 0, 'speed_mph': 0, 'number_wheels': 4, 'registration_number': 'MCL P1', 'last_mot_date': '23/08/2020'}\n"
]
}
],
"source": [
"# Create a new car object\n",
"mclaren_p1 = Car(number_engines = 1,\n",
" engine_horsepower_kw = 673,\n",
" chassis_height_mm = 1188,\n",
" chassis_width_mm = 1946,\n",
" chassis_depth_mm = 4588,\n",
" make = 'McLaren',\n",
" model = 'P1',\n",
" year_manufactured = 2013,\n",
" maximum_speed_mph = 217,\n",
" acceleration_rate_mps = 20,\n",
" deceleration_rate_mps = 50,\n",
" registration_number = 'MCL P1')\n",
"\n",
"# Print a string representation of the car object\n",
"print(mclaren_p1)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"217\n",
"23/08/2020\n",
"4\n"
]
}
],
"source": [
"# Access an attribute that is set in the Vehicle superclass\n",
"print(mclaren_p1.maximum_speed_mph)\n",
"\n",
"# Access an attribute that is set in the RoadVehicle superclass\n",
"print(mclaren_p1.last_mot_date)\n",
"\n",
"# Access an attribute that is set in the Car subclass\n",
"print(mclaren_p1.number_wheels)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"23/08/2020 21:30:40: McLaren P1 current speed: 0mph\n",
"23/08/2020 21:30:41: McLaren P1 current speed: 20mph\n",
"23/08/2020 21:30:42: McLaren P1 current speed: 40mph\n",
"23/08/2020 21:30:43: McLaren P1 current speed: 60mph\n",
"23/08/2020 21:30:44: McLaren P1 current speed: 80mph\n",
"23/08/2020 21:30:45: McLaren P1 current speed: 100mph\n",
"23/08/2020 21:30:46: McLaren P1 current speed: 120mph\n",
"23/08/2020 21:30:47: McLaren P1 current speed: 140mph\n",
"23/08/2020 21:30:48: McLaren P1 current speed: 160mph\n",
"23/08/2020 21:30:49: McLaren P1 current speed: 180mph\n",
"23/08/2020 21:30:50: McLaren P1 current speed: 200mph\n",
"23/08/2020 21:30:51: McLaren P1 current speed: 217mph\n",
"None\n"
]
}
],
"source": [
"# Invoke a method that is defined in the Vehicle superclass\n",
"print(mclaren_p1.accelerate())"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"23/08/2020 21:30:52: McLaren P1 current speed: 217mph\n",
"23/08/2020 21:30:53: McLaren P1 current speed: 167mph\n",
"23/08/2020 21:30:54: McLaren P1 current speed: 117mph\n",
"23/08/2020 21:30:55: McLaren P1 current speed: 67mph\n",
"23/08/2020 21:30:56: McLaren P1 current speed: 17mph\n",
"23/08/2020 21:30:57: McLaren P1 current speed: 0mph\n",
"None\n"
]
}
],
"source": [
"# Invoke a method that is defined in the Car class that itself invokes methods defined in the Vehicle superclass\n",
"print(mclaren_p1.avoid_collision())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.3.4. Overriding Methods"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Aircraft{'number_engines': 4, 'engine_horsepower_kw': 670, 'chassis_height_mm': 24100, 'chassis_width_mm': 79800, 'chassis_depth_mm': 72700, 'make': 'Airbus', 'model': 'A380', 'year_manufactured': 2005, 'maximum_speed_mph': 736, 'acceleration_rate_mps': 30, 'deceleration_rate_mps': 30, 'mileage_miles': 0, 'speed_mph': 0, 'minimum_speed_mph': 150}\n"
]
}
],
"source": [
"# Create a new aircraft object\n",
"airbus_a380 = Aircraft(number_engines = 4,\n",
" engine_horsepower_kw = 670,\n",
" chassis_height_mm = 24100,\n",
" chassis_width_mm = 79800,\n",
" chassis_depth_mm = 72700,\n",
" make = 'Airbus',\n",
" model = 'A380',\n",
" year_manufactured = 2005,\n",
" maximum_speed_mph = 736,\n",
" acceleration_rate_mps = 30,\n",
" deceleration_rate_mps = 30,\n",
" minimum_speed_mph = 150)\n",
"\n",
"# Print a string representation of the aircraft object\n",
"print(airbus_a380)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"24/08/2020 10:04:06: Airbus A380 current speed: 0mph\n",
"24/08/2020 10:04:07: Airbus A380 current speed: 30mph\n",
"24/08/2020 10:04:08: Airbus A380 current speed: 60mph\n",
"24/08/2020 10:04:09: Airbus A380 current speed: 90mph\n",
"24/08/2020 10:04:10: Airbus A380 current speed: 120mph\n",
"24/08/2020 10:04:11: Airbus A380 current speed: 150mph\n",
"24/08/2020 10:04:12: Airbus A380 current speed: 180mph\n",
"24/08/2020 10:04:13: Airbus A380 current speed: 210mph\n",
"24/08/2020 10:04:14: Airbus A380 current speed: 240mph\n",
"24/08/2020 10:04:15: Airbus A380 current speed: 270mph\n",
"24/08/2020 10:04:16: Airbus A380 current speed: 300mph\n",
"24/08/2020 10:04:17: Airbus A380 current speed: 330mph\n",
"24/08/2020 10:04:18: Airbus A380 current speed: 360mph\n",
"24/08/2020 10:04:19: Airbus A380 current speed: 390mph\n",
"24/08/2020 10:04:20: Airbus A380 current speed: 420mph\n",
"24/08/2020 10:04:21: Airbus A380 current speed: 450mph\n",
"24/08/2020 10:04:22: Airbus A380 current speed: 480mph\n",
"24/08/2020 10:04:23: Airbus A380 current speed: 510mph\n",
"24/08/2020 10:04:24: Airbus A380 current speed: 540mph\n",
"24/08/2020 10:04:25: Airbus A380 current speed: 570mph\n",
"24/08/2020 10:04:26: Airbus A380 current speed: 600mph\n",
"24/08/2020 10:04:27: Airbus A380 current speed: 630mph\n",
"24/08/2020 10:04:28: Airbus A380 current speed: 660mph\n",
"24/08/2020 10:04:29: Airbus A380 current speed: 690mph\n",
"24/08/2020 10:04:30: Airbus A380 current speed: 720mph\n",
"24/08/2020 10:04:31: Airbus A380 current speed: 736mph\n",
"None\n"
]
}
],
"source": [
"# Invoke a method that is defined in the Vehicle superclass\n",
"print(airbus_a380.accelerate())"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"24/08/2020 10:04:53: Airbus A380 current speed: 736mph\n",
"24/08/2020 10:04:54: Airbus A380 current speed: 706mph\n",
"24/08/2020 10:04:55: Airbus A380 current speed: 676mph\n",
"24/08/2020 10:04:56: Airbus A380 current speed: 646mph\n",
"24/08/2020 10:04:57: Airbus A380 current speed: 616mph\n",
"24/08/2020 10:04:58: Airbus A380 current speed: 586mph\n",
"24/08/2020 10:04:59: Airbus A380 current speed: 556mph\n",
"24/08/2020 10:05:00: Airbus A380 current speed: 526mph\n",
"24/08/2020 10:05:01: Airbus A380 current speed: 496mph\n",
"24/08/2020 10:05:02: Airbus A380 current speed: 466mph\n",
"24/08/2020 10:05:03: Airbus A380 current speed: 436mph\n",
"24/08/2020 10:05:04: Airbus A380 current speed: 406mph\n",
"24/08/2020 10:05:05: Airbus A380 current speed: 376mph\n",
"24/08/2020 10:05:06: Airbus A380 current speed: 346mph\n",
"24/08/2020 10:05:07: Airbus A380 current speed: 316mph\n",
"24/08/2020 10:05:08: Airbus A380 current speed: 286mph\n",
"24/08/2020 10:05:09: Airbus A380 current speed: 256mph\n",
"24/08/2020 10:05:10: Airbus A380 current speed: 226mph\n",
"24/08/2020 10:05:11: Airbus A380 current speed: 196mph\n",
"24/08/2020 10:05:12: Airbus A380 current speed: 166mph\n",
"24/08/2020 10:05:13: Airbus A380 current speed: 150mph\n",
"None\n"
]
}
],
"source": [
"# Invoke a method that is defined in the Aircraft class that overrides a method defined in the Vehicle superclass\n",
"print(airbus_a380.brake())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.3.6. Method Resolution Order"
]
},
{
"cell_type": "code",
"execution_count": 103,
"metadata": {},
"outputs": [],
"source": [
"# Define a simple superclass\n",
"class ClassA:\n",
" \n",
" var1 = 'A'\n",
" \n",
" def __init__(self, a1, a2, a3):\n",
" self.attr1 = a1\n",
" self.attr2 = a2\n",
" self.attr3 = a3\n",
" \n",
" def method1(self):\n",
" return self.attr1 + self.attr2\n",
"\n",
"\n",
"# Define a simple class derived from ClassA\n",
"class ClassB(ClassA):\n",
" \n",
" var1 = 'B'\n",
" \n",
" def __init__(self, b1, b2, b3):\n",
" super().__init__(b1, b2, b3)\n",
" self.attr4 = b2 * b3\n",
" \n",
" def method1(self):\n",
" return self.attr1 * self.attr2\n",
"\n",
"\n",
"# Define another simple class derived from ClassA\n",
"class ClassC(ClassA):\n",
" \n",
" def __init__(self, c1, c2, c3):\n",
" super().__init__(c1, c2, c3)\n",
" self.attr4 = c2 - c3\n",
" \n",
" def method1(self):\n",
" return self.attr1 - self.attr2\n",
"\n",
"\n",
"# Define a class that is derived from both ClassB and ClassC\n",
"class ClassD(ClassB, ClassC):\n",
" pass"
]
},
{
"cell_type": "code",
"execution_count": 106,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ClassB attr1: 1\n",
"ClassB attr2: 2\n",
"ClassB attr3: 3\n",
"ClassB attr4: 6\n",
"ClassB var1: B\n",
"ClassB method1(): 2\n"
]
}
],
"source": [
"# Create and test an instance of ClassB\n",
"class_b_object = ClassB(1, 2, 3)\n",
"print(f'ClassB attr1: {class_b_object.attr1}')\n",
"print(f'ClassB attr2: {class_b_object.attr2}')\n",
"print(f'ClassB attr3: {class_b_object.attr3}')\n",
"print(f'ClassB attr4: {class_b_object.attr4}')\n",
"print(f'ClassB var1: {class_b_object.var1}')\n",
"print(f'ClassB method1(): {class_b_object.method1()}')"
]
},
{
"cell_type": "code",
"execution_count": 107,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ClassC attr1: 1\n",
"ClassC attr2: 2\n",
"ClassC attr3: 3\n",
"ClassC attr4: -1\n",
"ClassC var1: A\n",
"ClassC method1(): -1\n"
]
}
],
"source": [
"# Create and test an instance of ClassC\n",
"class_c_object = ClassC(1, 2, 3)\n",
"print(f'ClassC attr1: {class_c_object.attr1}')\n",
"print(f'ClassC attr2: {class_c_object.attr2}')\n",
"print(f'ClassC attr3: {class_c_object.attr3}')\n",
"print(f'ClassC attr4: {class_c_object.attr4}')\n",
"print(f'ClassC var1: {class_c_object.var1}')\n",
"print(f'ClassC method1(): {class_c_object.method1()}')"
]
},
{
"cell_type": "code",
"execution_count": 108,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ClassD attr1: 1\n",
"ClassD attr2: 2\n",
"ClassD attr3: 3\n",
"ClassD attr4: 6\n",
"ClassD var1: B\n",
"ClassD method1(): 2\n"
]
}
],
"source": [
"# Create and test an instance of ClassD\n",
"class_d_object = ClassD(1, 2, 3)\n",
"print(f'ClassD attr1: {class_d_object.attr1}')\n",
"print(f'ClassD attr2: {class_d_object.attr2}')\n",
"print(f'ClassD attr3: {class_d_object.attr3}')\n",
"print(f'ClassD attr4: {class_d_object.attr4}')\n",
"print(f'ClassD var1: {class_d_object.var1}')\n",
"print(f'ClassD method1(): {class_d_object.method1()}')"
]
},
{
"cell_type": "code",
"execution_count": 115,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ClassA MRO:\n",
"(, )\n",
"\n",
"ClassB MRO:\n",
"(, , )\n",
"\n",
"ClassC MRO:\n",
"(, , )\n",
"\n",
"ClassD MRO:\n",
"(, , , , )\n",
"\n"
]
}
],
"source": [
"# Access the resolved MRO for each class\n",
"print(f'ClassA MRO:\\n{ClassA.__mro__}\\n')\n",
"print(f'ClassB MRO:\\n{ClassB.__mro__}\\n')\n",
"print(f'ClassC MRO:\\n{ClassC.__mro__}\\n')\n",
"print(f'ClassD MRO:\\n{ClassD.__mro__}\\n')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.3.7. Finding Subclasses"
]
},
{
"cell_type": "code",
"execution_count": 119,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['RoadVehicle', 'Aircraft']\n",
"[, ]\n"
]
}
],
"source": [
"# List the names of all the subclasses directly derived from the Vehicle class\n",
"print([cls.__name__ for cls in Vehicle.__subclasses__()])\n",
"\n",
"# List all the subclasses directly derived from the Vehicle class\n",
"print(Vehicle.__subclasses__())"
]
},
{
"cell_type": "code",
"execution_count": 125,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{, , }\n"
]
}
],
"source": [
"# Create a function to list all direct and indirect subclasses of a given class\n",
"def find_all_subclasses(cls):\n",
" return set(cls.__subclasses__()).union(\n",
" [subclass for c in cls.__subclasses__() for subclass in find_all_subclasses(c)])\n",
"\n",
"# List all the subclasses that are both directly and indirectly derived from the Vehicle class\n",
"print(find_all_subclasses(Vehicle))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.4. Constructors\n",
"#### 2.4.2. Non-Parameterized Constructor"
]
},
{
"cell_type": "code",
"execution_count": 128,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating an instance of ClassX...\n",
"138\n"
]
}
],
"source": [
"# Define a class with a non-parameterized constructor\n",
"class ClassX:\n",
" \n",
" def __init__(self):\n",
" print(f'Creating an instance of {type(self).__name__}...')\n",
" \n",
" def sum(self, a, b):\n",
" return a + b\n",
" \n",
"# Create a new instance of ClassX\n",
"class_x_object = ClassX()\n",
"\n",
"# Invoke a method on the new object of type ClassX\n",
"print(class_x_object.sum(100, 38))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.4.3. Default Constructor"
]
},
{
"cell_type": "code",
"execution_count": 129,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"260\n"
]
}
],
"source": [
"# Define a class without an explicit constructor\n",
"class ClassY:\n",
" \n",
" def product(self, a, b):\n",
" return a * b\n",
"\n",
"# Create a new instance of ClassY\n",
"class_y_object = ClassY()\n",
"\n",
"# Invoke a method on the new object of type ClassY\n",
"print(class_y_object.product(13, 20))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.4.4. Explicit Invocation"
]
},
{
"cell_type": "code",
"execution_count": 136,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Creating an instance of ClassZ...\n",
"3\n"
]
}
],
"source": [
"# Define a class with a constructor that explicitly invokes the constructor of another class\n",
"class ClassZ:\n",
" \n",
" def __init__(self):\n",
" ClassX.__init__(self)\n",
" \n",
" def modulus(self, a, b):\n",
" return a % b\n",
"\n",
"# Create a new instance of ClassZ\n",
"class_z_object = ClassZ()\n",
"\n",
"# Invoke a method on the new object of type ClassZ\n",
"print(class_z_object.modulus(103, 4))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.5. Name Mangling"
]
},
{
"cell_type": "code",
"execution_count": 138,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"04/08/1961\n"
]
}
],
"source": [
"# Define a class that contains 'private' variables\n",
"class User:\n",
" \n",
" def __init__(self, fname, lname, email, dob, postal_address):\n",
" self.fname = fname\n",
" self.lname = lname\n",
" self.email = email\n",
" self.__dob = dob\n",
" self.__postal_address = postal_address\n",
" \n",
" def display_dob(self):\n",
" print(self.__dob)\n",
" \n",
" def display_postal_address(self):\n",
" print(self.__postal_address)\n",
"\n",
"# Create a new user\n",
"barack_obama_user = User('Barack', 'Obama', 'bobama@whitehouse.gov', '04/08/1961', '1600 Pennsylvania Avenue')\n",
"\n",
"# Display the user's private dob using the display_dob() method\n",
"barack_obama_user.display_dob()"
]
},
{
"cell_type": "code",
"execution_count": 140,
"metadata": {},
"outputs": [
{
"ename": "AttributeError",
"evalue": "'User' object has no attribute 'dob'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Display the user's private dob by directly accessing the dob attribute using dot notation\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbarack_obama_user\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdob\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m: 'User' object has no attribute 'dob'"
]
}
],
"source": [
"# Display the user's private dob by directly accessing the dob attribute using dot notation\n",
"print(barack_obama_user.dob)"
]
},
{
"cell_type": "code",
"execution_count": 141,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"04/08/1961\n"
]
}
],
"source": [
"# Display the user's private dob indirectly by accessing the mangled dob attribute\n",
"print(barack_obama_user._User__dob)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2.6. Common Functions"
]
},
{
"cell_type": "code",
"execution_count": 180,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True\n",
"False\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"True\n",
"True\n",
"False\n",
"True\n",
"True\n",
"True\n",
"True\n",
"True\n",
"True\n",
"True\n",
"False\n",
"True\n",
"\n",
"True\n",
"True\n",
"True\n",
"False\n",
"True\n"
]
}
],
"source": [
"# Create a new aircraft object\n",
"airbus_a380 = Aircraft(number_engines = 4,\n",
" engine_horsepower_kw = 670,\n",
" chassis_height_mm = 24100,\n",
" chassis_width_mm = 79800,\n",
" chassis_depth_mm = 72700,\n",
" make = 'Airbus',\n",
" model = 'A380',\n",
" year_manufactured = 2005,\n",
" maximum_speed_mph = 736,\n",
" acceleration_rate_mps = 30,\n",
" deceleration_rate_mps = 30,\n",
" minimum_speed_mph = 150)\n",
"\n",
"# hasattr()\n",
"print( hasattr(airbus_a380, 'engine_horsepower_kw') )\n",
"print( hasattr(airbus_a380, 'last_mot_date') )\n",
"print()\n",
"\n",
"# type()\n",
"print( type(airbus_a380) )\n",
"print( type([1, 2, 3]) )\n",
"print( type(('a', 'b', 'c')) )\n",
"print( type({1: 'a', 2: 'b', 3: 'c'}) )\n",
"print( type(Vehicle) )\n",
"print( type(str) )\n",
"print( type(int) )\n",
"print( type(str) )\n",
"print( type('Hello World!') )\n",
"print( type(38) )\n",
"print( type(0.5) )\n",
"print( type(True) )\n",
"print( type(False) )\n",
"print( type(47 & 55) )\n",
"print( type(None) )\n",
"print()\n",
"\n",
"# issubclass()\n",
"print( issubclass(type(airbus_a380), Vehicle) )\n",
"print( issubclass(Aircraft, Vehicle) )\n",
"print( issubclass(Vehicle, Aircraft) )\n",
"print( issubclass(Vehicle, Vehicle) )\n",
"print( issubclass(Vehicle, object) )\n",
"print( issubclass(str, object) )\n",
"print( issubclass(list, object) )\n",
"print( issubclass(tuple, object) )\n",
"print( issubclass(dict, object) )\n",
"print( issubclass(type(ClassD(1, 2, 3)), ClassA) )\n",
"print( issubclass(type(None), ClassA) )\n",
"print( issubclass(type(None), object) )\n",
"print()\n",
"\n",
"# isinstance()\n",
"print( isinstance(airbus_a380, Aircraft) )\n",
"print( isinstance(airbus_a380, Vehicle) )\n",
"print( isinstance(airbus_a380, object) )\n",
"print( isinstance(airbus_a380, Car) )\n",
"print( isinstance(None, object) )"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.8"
}
},
"nbformat": 4,
"nbformat_minor": 4
}