Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
329 changes: 329 additions & 0 deletions 00_Python/04-Object-Oriented-Programming/01-Class-and-Objects.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Class and Objects\n",
"\n",
"A class is a blueprint or a template for creating objects, which are instances of the class. Classes encapsulate data and the behavior that operates on that data. A class defines a set of attributes and methods that can be used to create objects. In Python, you can define a class using the `class` keyword. Attributes and methods are the two key components of a python class. Attributes are the characteristics or properties of an object, while methods are the functions that are associated with the object.\n",
"\n",
"Here's an example of a simple class definition:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"class Person:\n",
" def __init__(self, name, age, sex):\n",
" self.name = name\n",
" self.age = age\n",
" self.sex = sex\n",
" \n",
" def gender(self):\n",
" print(f\"{self.name} is {self.sex}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This class, called `Person`, has three attributes (`name`, `age`, and `sex`) and one method (`gender`). The `__init__` method is a special method (**constructor**) that is called when a new instance of the class is created. It takes three arguments (`name`, `age`, and `sex`) and initializes the corresponding attributes. The `gender` method is a simple method that prints a message to the console.\n",
"\n",
"To create an instance of the `Person` class, you can simply call the class with the appropriate arguments:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<class '__main__.Person'>\n"
]
}
],
"source": [
"person1 = Person(\"Luluw\", 23, \"Male\")\n",
"print(type(person1)) "
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Luluw, 23, Male\n"
]
}
],
"source": [
"print(person1.name, person1.age, person1.sex, sep=\", \")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can call the methods of an instance using the dot notation as well."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Luluw is Male\n"
]
}
],
"source": [
"person1.gender()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Types of Attributes\n",
"\n",
"#### 1. Instance Attributes\n",
"\n",
"These are the attributes that belong to instances of a class. They are defined within the constructor method `__init__` and can be accessed using the `self` keyword like `self.name`, `self.age`, and `self.sex` in the above `Person` class.. They are initialized when a new instance of the class is created.\n",
"\n",
"#### 2. Class attributes\n",
"\n",
"Class attributes are attributes that belong to the class itself. They are defined outside the constructor method `__init__` and can be accessed using the class name. Class attributes are shared by all instances of the class like `count` attribute in the `Person` class below.\n",
"\n",
"## Types of Methods\n",
"\n",
"#### 1. Instance methods\n",
"\n",
"The most common type of method in Python. These are the methods that operate on an instance of a class and have access to the instance's attributes. Instance methods are defined within the class and are called on instances of the class like `gender` method of the `Person` class above.\n",
"\n",
"#### 2. Class methods\n",
"\n",
"Class methods are methods that operate on the class itself rather than on instances of the class. They are defined using the `@classmethod` decorator and take the class itself as the first argument like `get_count` method of `Person` class below.\n",
"\n",
"#### 3. Static methods\n",
"\n",
"Static methods are methods that do not operate on the instance or the class, but are related to the class in some way. They are defined using the `@staticmethod` decorator and do not take the instance or the class as arguments like `get_full_name` in `Person` class below."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class Person:\n",
" count = 0 # Class Attribute/Variable\n",
"\n",
" def __init__(self, name):\n",
" self.name = name\n",
" Person.count += 1\n",
"\n",
" @classmethod\n",
" def get_count(cls): # Defining class method\n",
" return cls.count\n",
"\n",
" @staticmethod\n",
" def get_full_name(firstname, secondname):\n",
" return f\"{firstname} {secondname}\"\n"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0\n",
"1\n",
"2\n",
"Chandler Bing\n"
]
}
],
"source": [
"print(Person.get_count())\n",
"\n",
"person1 = Person(\"Alice\")\n",
"print(Person.get_count())\n",
"\n",
"person2 = Person(\"Bob\")\n",
"print(Person.get_count())\n",
"\n",
"print(Person.get_full_name('Chandler', 'Bing'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this example, we call the `get_count` method on the `Person` class to get the initial value of the `count` attribute (which is `0`). We then create two instances of the `Person` class (`person1` and `person2`), which increment the count attribute each time. Finally, we call the `get_count` method again to get the current value of the `count` attribute (which is `2`).\n",
"\n",
"This is just a brief introduction to OOP in Python. There are many more advanced features and techniques that you can use to create powerful and flexible programs."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"✅ **Key Differences:**\n",
"| Feature | Instance Method (Default) | Class Method (`@classmethod`) | Static Method (`@staticmethod`) |\n",
"|------------------|------------------|-----------------|-----------------|\n",
"| First Parameter | `self` (instance) | `cls` (class) | No `self` or `cls` |\n",
"| Access Instance Variables? | ✅ Yes | ❌ No | ❌ No |\n",
"| Access Class Variables? | ✅ Yes | ✅ Yes | ❌ No |\n",
"| Can Modify Instance State? | ✅ Yes | ❌ No | ❌ No |"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class Car:\n",
" count = 0 # Class Attribute/Variable \n",
" \n",
" def __init__(self, brand_name: str, car_type: str, year: int, price: float) -> None:\n",
" # Car Attributes\n",
" self.brand_name: str = brand_name\n",
" self.car_type: str = car_type\n",
" self.year: int = year\n",
" self.price: float = price\n",
"\n",
" # Incrementing Car class instance count\n",
" Car.count += 1\n",
"\n",
"\n",
" def display_info(self) -> str:\n",
" \"\"\"Display the details of car\"\"\"\n",
" return f\"\"\"\n",
" ID_creation: {Car.count}\n",
" Brand: {self.brand_name},\n",
" Type: {self.car_type},\n",
" Year: {self.year},\n",
" Price: {self.price:,.2f}$\n",
" \"\"\"\n",
"\n",
" def get_discounted_price(self) -> float:\n",
" \"\"\"Return the final price after deducting discount\"\"\"\n",
" return self.price - (self.price * 0.05) # 0.05 is discount rate\n",
" \n",
" @classmethod\n",
" def from_string(cls, car_str: str) -> \"Car\":\n",
" brand, car_type, year, price = [x.strip() for x in car_str.split(\",\")]\n",
" return cls(brand, car_type, int(year), float(price))\n",
"\n",
" @staticmethod\n",
" def is_luxury(price: float) -> bool:\n",
" return price > 50000"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this example, we call the `display_info` method on the `Car` class to get the details of a car. We then create two instances of the `Car` class (`car1` and `car2`) using both the constructor and the `from_string` class method. After that, we call the `get_discounted_price` method to get the price after applying a **5% discount**. Finally, we use the `is_luxury` static method to check whether a car is luxury (if its price is above **$50,000**)."
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
" ID_creation: 1\n",
" Brand: Tesla,\n",
" Type: Electronic,\n",
" Year: 2024,\n",
" Price: 55,000.00$\n",
" \n",
"Discounted Price: 52250.0\n",
"True\n"
]
}
],
"source": [
"car1 = Car(\"Tesla\", \"Electronic\", 2024, 55000)\n",
"car1_info, car1_price = car1.display_info(), car1.get_discounted_price()\n",
"print(car1_info)\n",
"print(\"Discounted Price:\", car1_price)\n",
"print(Car.is_luxury(car1.price))\n"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
" ID_creation: 2\n",
" Brand: Toyota,\n",
" Type: Sedan,\n",
" Year: 2023,\n",
" Price: 32,000.00$\n",
" \n",
"Discounted Price: 30400.0\n",
"False\n"
]
}
],
"source": [
"car2 = Car.from_string(\"Toyota, Sedan, 2023, 32000\")\n",
"print(car2.display_info())\n",
"print(\"Discounted Price:\", car2.get_discounted_price())\n",
"print(Car.is_luxury(car2.price))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "env",
"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.11.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading