kopia lustrzana https://github.com/animator/learn-python
471 wiersze
12 KiB
Markdown
471 wiersze
12 KiB
Markdown
![]() |
---
|
||
|
jupyter:
|
||
|
colab:
|
||
|
kernelspec:
|
||
|
display_name: Python 3
|
||
|
name: python3
|
||
|
language_info:
|
||
|
name: python
|
||
|
nbformat: 4
|
||
|
nbformat_minor: 0
|
||
|
---
|
||
|
|
||
|
::: {.cell .markdown id="WpcHLEIgeEdz"}
|
||
|
**PYTHON OOP CONCEPTS**
|
||
|
:::
|
||
|
|
||
|
::: {.cell .markdown id="3j1W5YpNeEmS"}
|
||
|
In Python object-oriented Programming (OOPs) is a programming paradigm
|
||
|
that uses objects and classes in programming. It aims to implement
|
||
|
real-world entities like inheritance, polymorphisms, encapsulation, etc.
|
||
|
in the programming. The main concept of object-oriented Programming
|
||
|
(OOPs) or oops concepts in Python is to bind the data and the functions
|
||
|
that work together as a single unit so that no other part of the code
|
||
|
can access this data.
|
||
|
|
||
|
**OOPs Concepts in Python**
|
||
|
|
||
|
1. Class in Python
|
||
|
|
||
|
2. Objects in Python
|
||
|
|
||
|
3. Polymorphism in Python
|
||
|
|
||
|
4. Encapsulation in Python
|
||
|
|
||
|
5. Inheritance in Python
|
||
|
|
||
|
6. Data Abstraction in Python
|
||
|
:::
|
||
|
|
||
|
::: {.cell .markdown id="3KQXMPlVeEyT"}
|
||
|
Python Class A class is a collection of objects. A class contains the
|
||
|
blueprints or the prototype from which the objects are being created. It
|
||
|
is a logical entity that contains some attributes and methods.
|
||
|
:::
|
||
|
|
||
|
::: {.cell .code execution_count="2" id="6CdZhHSMerae"}
|
||
|
|
||
|
```python
|
||
|
#Simple Class in Python
|
||
|
class Dog:
|
||
|
pass
|
||
|
```
|
||
|
|
||
|
:::
|
||
|
|
||
|
::: {.cell .markdown id="y5t7jyHAfAHl"}
|
||
|
**Python Objects** In object oriented programming Python, The object is
|
||
|
an entity that has a state and behavior associated with it. It may be
|
||
|
any real-world object like a mouse, keyboard, chair, table, pen, etc.
|
||
|
Integers, strings, floating-point numbers, even arrays, and
|
||
|
dictionaries, are all objects.
|
||
|
:::
|
||
|
|
||
|
::: {.cell .code execution_count="3" id="u8Y0G-hse-lm"}
|
||
|
|
||
|
```python
|
||
|
obj = Dog()
|
||
|
```
|
||
|
|
||
|
:::
|
||
|
|
||
|
::: {.cell .markdown id="\_FtRAPlNfLkb"}
|
||
|
**The Python **init** Method **
|
||
|
|
||
|
The **init** method is similar to constructors in C++ and Java. It is
|
||
|
run as soon as an object of a class is instantiated. The method is
|
||
|
useful to do any initialization you want to do with your object.
|
||
|
:::
|
||
|
|
||
|
::: {.cell .code execution_count="4" colab="{\"base_uri\":\"https://localhost:8080/\"}" id="aMmXUxLHfSz6" outputId="ed23bfbd-445a-4d02-ebba-c210471e0af2"}
|
||
|
|
||
|
```python
|
||
|
class Dog:
|
||
|
|
||
|
# class attribute
|
||
|
attr1 = "mammal"
|
||
|
|
||
|
# Instance attribute
|
||
|
def __init__(self, name):
|
||
|
self.name = name
|
||
|
|
||
|
# Object instantiation
|
||
|
Rodger = Dog("Rodger")
|
||
|
Tommy = Dog("Tommy")
|
||
|
|
||
|
# Accessing class attributes
|
||
|
print("Rodger is a {}".format(Rodger.__class__.attr1))
|
||
|
print("Tommy is also a {}".format(Tommy.__class__.attr1))
|
||
|
|
||
|
# Accessing instance attributes
|
||
|
print("My name is {}".format(Rodger.name))
|
||
|
print("My name is {}".format(Tommy.name))
|
||
|
```
|
||
|
|
||
|
::: {.output .stream .stdout}
|
||
|
Rodger is a mammal
|
||
|
Tommy is also a mammal
|
||
|
My name is Rodger
|
||
|
My name is Tommy
|
||
|
:::
|
||
|
:::
|
||
|
|
||
|
::: {.cell .markdown id="YFMnh417fZI6"}
|
||
|
**Inheritance**
|
||
|
|
||
|
In Python object oriented Programming, Inheritance is the capability of
|
||
|
one class to derive or inherit the properties from another class. The
|
||
|
class that derives properties is called the derived class or child class
|
||
|
and the class from which the properties are being derived is called the
|
||
|
base class or parent class.
|
||
|
|
||
|
Types of Inheritances:
|
||
|
|
||
|
- Single Inheritance
|
||
|
|
||
|
- Multilevel Inheritance
|
||
|
|
||
|
- Multiple Inheritance
|
||
|
|
||
|
- Hierarchial Inheritance
|
||
|
:::
|
||
|
|
||
|
::: {.cell .code execution_count="6" colab="{\"base_uri\":\"https://localhost:8080/\"}" id="PeQoseXogE2f" outputId="9b3a069e-c6f0-41b0-b5f3-704aa0f95160"}
|
||
|
|
||
|
```python
|
||
|
#Single Inheritance
|
||
|
# Parent class
|
||
|
class Animal:
|
||
|
def __init__(self, name, sound):
|
||
|
self.name = name
|
||
|
self.sound = sound
|
||
|
|
||
|
def make_sound(self):
|
||
|
print(f"{self.name} says {self.sound}")
|
||
|
|
||
|
# Child class inheriting from Animal
|
||
|
class Dog(Animal):
|
||
|
def __init__(self, name):
|
||
|
# Call the constructor of the parent class
|
||
|
super().__init__(name, "Woof")
|
||
|
|
||
|
# Child class inheriting from Animal
|
||
|
class Cat(Animal):
|
||
|
def __init__(self, name):
|
||
|
# Call the constructor of the parent class
|
||
|
super().__init__(name, "Meow")
|
||
|
|
||
|
# Creating objects of the derived classes
|
||
|
dog = Dog("Buddy")
|
||
|
cat = Cat("Whiskers")
|
||
|
|
||
|
# Accessing methods of the parent class
|
||
|
dog.make_sound()
|
||
|
cat.make_sound()
|
||
|
```
|
||
|
|
||
|
::: {.output .stream .stdout}
|
||
|
Buddy says Woof
|
||
|
Whiskers says Meow
|
||
|
:::
|
||
|
:::
|
||
|
|
||
|
::: {.cell .code execution_count="7" colab="{\"base_uri\":\"https://localhost:8080/\"}" id="CKEMq39BgSu9" outputId="b252ac43-6116-4a88-9ac9-0475f54e63c0"}
|
||
|
|
||
|
```python
|
||
|
#Multilevel Inheritance
|
||
|
# Parent class
|
||
|
class Animal:
|
||
|
def __init__(self, name):
|
||
|
self.name = name
|
||
|
|
||
|
def speak(self):
|
||
|
print(f"{self.name} speaks")
|
||
|
|
||
|
# Child class inheriting from Animal
|
||
|
class Dog(Animal):
|
||
|
def bark(self):
|
||
|
print(f"{self.name} barks")
|
||
|
|
||
|
# Grandchild class inheriting from Dog
|
||
|
class GermanShepherd(Dog):
|
||
|
def guard(self):
|
||
|
print(f"{self.name} guards")
|
||
|
|
||
|
# Creating objects of the derived classes
|
||
|
german_shepherd = GermanShepherd("Rocky")
|
||
|
|
||
|
# Accessing methods from all levels of inheritance
|
||
|
german_shepherd.speak() # Accessing method from the Animal class
|
||
|
german_shepherd.bark() # Accessing method from the Dog class
|
||
|
german_shepherd.guard() # Accessing method from the GermanShepherd class
|
||
|
```
|
||
|
|
||
|
::: {.output .stream .stdout}
|
||
|
Rocky speaks
|
||
|
Rocky barks
|
||
|
Rocky guards
|
||
|
:::
|
||
|
:::
|
||
|
|
||
|
::: {.cell .code execution_count="8" colab="{\"base_uri\":\"https://localhost:8080/\"}" id="wZ5qxZXBgdQ6" outputId="cd1c9d75-790c-49b3-8040-3334b896d779"}
|
||
|
|
||
|
```python
|
||
|
#Hierarchial Inheritance
|
||
|
# Parent class
|
||
|
class Animal:
|
||
|
def __init__(self, name):
|
||
|
self.name = name
|
||
|
|
||
|
def speak(self):
|
||
|
print(f"{self.name} speaks")
|
||
|
|
||
|
# Child class 1 inheriting from Animal
|
||
|
class Dog(Animal):
|
||
|
def bark(self):
|
||
|
print(f"{self.name} barks")
|
||
|
|
||
|
# Child class 2 inheriting from Animal
|
||
|
class Cat(Animal):
|
||
|
def meow(self):
|
||
|
print(f"{self.name} meows")
|
||
|
|
||
|
# Creating objects of the derived classes
|
||
|
dog = Dog("Buddy")
|
||
|
cat = Cat("Whiskers")
|
||
|
|
||
|
# Accessing methods from the parent and child classes
|
||
|
dog.speak() # Accessing method from the Animal class
|
||
|
dog.bark() # Accessing method from the Dog class
|
||
|
cat.speak() # Accessing method from the Animal class
|
||
|
cat.meow() # Accessing method from the Cat class
|
||
|
```
|
||
|
|
||
|
::: {.output .stream .stdout}
|
||
|
Buddy speaks
|
||
|
Buddy barks
|
||
|
Whiskers speaks
|
||
|
Whiskers meows
|
||
|
:::
|
||
|
:::
|
||
|
|
||
|
::: {.cell .code execution_count="9" colab="{\"base_uri\":\"https://localhost:8080/\"}" id="8nPMri12glO5" outputId="a3c93e8c-f10f-4cd7-c402-3500342c9e28"}
|
||
|
|
||
|
```python
|
||
|
#Multiple Inheritance
|
||
|
# Parent class 1
|
||
|
class Herbivore:
|
||
|
def eat_plants(self):
|
||
|
print("Eating plants")
|
||
|
|
||
|
# Parent class 2
|
||
|
class Carnivore:
|
||
|
def eat_meat(self):
|
||
|
print("Eating meat")
|
||
|
|
||
|
# Child class inheriting from both Herbivore and Carnivore
|
||
|
class Omnivore(Herbivore, Carnivore):
|
||
|
def eat(self):
|
||
|
print("Eating everything")
|
||
|
|
||
|
# Creating an object of the Omnivore class
|
||
|
omnivore = Omnivore()
|
||
|
|
||
|
# Accessing methods from both parent classes
|
||
|
omnivore.eat_plants() # Accessing method from Herbivore
|
||
|
omnivore.eat_meat() # Accessing method from Carnivore
|
||
|
omnivore.eat() # Accessing method from Omnivore
|
||
|
```
|
||
|
|
||
|
::: {.output .stream .stdout}
|
||
|
Eating plants
|
||
|
Eating meat
|
||
|
Eating everything
|
||
|
:::
|
||
|
:::
|
||
|
|
||
|
::: {.cell .markdown id="KSw-WMePgvCa"}
|
||
|
**Polymorphism** In object oriented Programming Python, Polymorphism
|
||
|
simply means having many forms
|
||
|
:::
|
||
|
|
||
|
::: {.cell .code execution_count="10" colab="{\"base_uri\":\"https://localhost:8080/\"}" id="cIYtM2_Pg8Ja" outputId="e887848d-060a-4317-a805-cfb0ca4e187f"}
|
||
|
|
||
|
```python
|
||
|
class Bird:
|
||
|
|
||
|
def intro(self):
|
||
|
print("There are many types of birds.")
|
||
|
|
||
|
def flight(self):
|
||
|
print("Most of the birds can fly but some cannot.")
|
||
|
|
||
|
class sparrow(Bird):
|
||
|
|
||
|
def flight(self):
|
||
|
print("Sparrows can fly.")
|
||
|
|
||
|
class ostrich(Bird):
|
||
|
|
||
|
def flight(self):
|
||
|
print("Ostriches cannot fly.")
|
||
|
|
||
|
obj_bird = Bird()
|
||
|
obj_spr = sparrow()
|
||
|
obj_ost = ostrich()
|
||
|
|
||
|
obj_bird.intro()
|
||
|
obj_bird.flight()
|
||
|
|
||
|
obj_spr.intro()
|
||
|
obj_spr.flight()
|
||
|
|
||
|
obj_ost.intro()
|
||
|
obj_ost.flight()
|
||
|
```
|
||
|
|
||
|
::: {.output .stream .stdout}
|
||
|
There are many types of birds.
|
||
|
Most of the birds can fly but some cannot.
|
||
|
There are many types of birds.
|
||
|
Sparrows can fly.
|
||
|
There are many types of birds.
|
||
|
Ostriches cannot fly.
|
||
|
:::
|
||
|
:::
|
||
|
|
||
|
::: {.cell .markdown id="NzsPIifmg-FI"}
|
||
|
**Python Encapsulation**
|
||
|
|
||
|
In Python object oriented programming, Encapsulation is one of the
|
||
|
fundamental concepts in object-oriented programming (OOP). It describes
|
||
|
the idea of wrapping data and the methods that work on data within one
|
||
|
unit. This puts restrictions on accessing variables and methods directly
|
||
|
and can prevent the accidental modification of data. To prevent
|
||
|
accidental change, an object's variable can only be changed by an
|
||
|
object's method. Those types of variables are known as private
|
||
|
variables.
|
||
|
:::
|
||
|
|
||
|
::: {.cell .code execution_count="11" colab="{\"base_uri\":\"https://localhost:8080/\"}" id="etbhALMHhGb9" outputId="75f27d20-7cee-4c85-b722-b9beb5ffe2b8"}
|
||
|
|
||
|
```python
|
||
|
class Car:
|
||
|
def __init__(self, make, model, year):
|
||
|
self._make = make # Encapsulated attribute with single underscore
|
||
|
self._model = model # Encapsulated attribute with single underscore
|
||
|
self._year = year # Encapsulated attribute with single underscore
|
||
|
self._odometer_reading = 0 # Encapsulated attribute with single underscore
|
||
|
|
||
|
def get_make(self):
|
||
|
return self._make
|
||
|
|
||
|
def get_model(self):
|
||
|
return self._model
|
||
|
|
||
|
def get_year(self):
|
||
|
return self._year
|
||
|
|
||
|
def get_odometer_reading(self):
|
||
|
return self._odometer_reading
|
||
|
|
||
|
def update_odometer(self, mileage):
|
||
|
if mileage >= self._odometer_reading:
|
||
|
self._odometer_reading = mileage
|
||
|
else:
|
||
|
print("You can't roll back an odometer!")
|
||
|
|
||
|
def increment_odometer(self, miles):
|
||
|
self._odometer_reading += miles
|
||
|
|
||
|
# Creating an instance of the Car class
|
||
|
my_car = Car("Toyota", "Camry", 2021)
|
||
|
|
||
|
# Accessing encapsulated attributes through methods
|
||
|
print("Make:", my_car.get_make())
|
||
|
print("Model:", my_car.get_model())
|
||
|
print("Year:", my_car.get_year())
|
||
|
|
||
|
# Modifying encapsulated attribute through method
|
||
|
my_car.update_odometer(100)
|
||
|
print("Odometer Reading:", my_car.get_odometer_reading())
|
||
|
|
||
|
# Incrementing odometer reading
|
||
|
my_car.increment_odometer(50)
|
||
|
print("Odometer Reading after increment:", my_car.get_odometer_reading())
|
||
|
```
|
||
|
|
||
|
::: {.output .stream .stdout}
|
||
|
Make: Toyota
|
||
|
Model: Camry
|
||
|
Year: 2021
|
||
|
Odometer Reading: 100
|
||
|
Odometer Reading after increment: 150
|
||
|
:::
|
||
|
:::
|
||
|
|
||
|
::: {.cell .markdown id="hJkQ9Tn5hUEV"}
|
||
|
**Data Abstraction** It hides unnecessary code details from the user.
|
||
|
Also, when we do not want to give out sensitive parts of our code
|
||
|
implementation and this is where data abstraction came.
|
||
|
:::
|
||
|
|
||
|
::: {.cell .code execution_count="12" colab="{\"base_uri\":\"https://localhost:8080/\"}" id="FoMRMWEEhc-Z" outputId="3a77fd0d-8116-4997-c35f-dfebfc786b72"}
|
||
|
|
||
|
```python
|
||
|
from abc import ABC, abstractmethod
|
||
|
|
||
|
# Abstract class defining the interface for a Shape
|
||
|
class Shape(ABC):
|
||
|
def __init__(self, name):
|
||
|
self.name = name
|
||
|
|
||
|
@abstractmethod
|
||
|
def area(self):
|
||
|
pass
|
||
|
|
||
|
@abstractmethod
|
||
|
def perimeter(self):
|
||
|
pass
|
||
|
|
||
|
# Concrete class implementing the Shape interface for a Rectangle
|
||
|
class Rectangle(Shape):
|
||
|
def __init__(self, name, length, width):
|
||
|
super().__init__(name)
|
||
|
self.length = length
|
||
|
self.width = width
|
||
|
|
||
|
def area(self):
|
||
|
return self.length * self.width
|
||
|
|
||
|
def perimeter(self):
|
||
|
return 2 * (self.length + self.width)
|
||
|
|
||
|
# Concrete class implementing the Shape interface for a Circle
|
||
|
class Circle(Shape):
|
||
|
def __init__(self, name, radius):
|
||
|
super().__init__(name)
|
||
|
self.radius = radius
|
||
|
|
||
|
def area(self):
|
||
|
return 3.14 * self.radius * self.radius
|
||
|
|
||
|
def perimeter(self):
|
||
|
return 2 * 3.14 * self.radius
|
||
|
|
||
|
# Creating objects of the derived classes
|
||
|
rectangle = Rectangle("Rectangle", 5, 4)
|
||
|
circle = Circle("Circle", 3)
|
||
|
|
||
|
# Accessing methods defined by the Shape interface
|
||
|
print(f"{rectangle.name}: Area = {rectangle.area()}, Perimeter = {rectangle.perimeter()}")
|
||
|
print(f"{circle.name}: Area = {circle.area()}, Perimeter = {circle.perimeter()}")
|
||
|
```
|
||
|
|
||
|
::: {.output .stream .stdout}
|
||
|
Rectangle: Area = 20, Perimeter = 18
|
||
|
Circle: Area = 28.259999999999998, Perimeter = 18.84
|
||
|
:::
|
||
|
:::
|