OOP

part 1

What is OOP and why do we need it?

The 4 principles

  • Abstraction

  • Encapsulation

  • Inheritance

  • Polymorphism

Abstraction

 

Class

  • __init__() is the class constructor of Python classes
  • The first argument is always the instance itself (self)
  • Classes are instantiated by "calling" them with the arguments expected in the __init__ method (You can use the * syntax here as well
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y


a = Point(1, 2)
b = Point(x=1, y=2)
class Point:
    def __init__(self, *, x, y):
        self.x = x
        self.y = y

Methods

class Panda:
    def __init__(self, name, age, weight):
        self.name = name
        self.age = age
        self.weight = weight

    def eat(self, kg):
        if self.weight < 1000:
            self.weight += kg

    def celebrate_birthday(self):
        self.age += 1
  • All class methods receive self as first argument

Encapsulation

 

Private/Protected

  • Everything in a Python class is public by default
  • If a method or an attribute starts with _ it is considered "protected"
  • If a method or an attribute starts with __ it is considered "private". This is called Name mangling and Python interpreter does it for us.

Private/Protected

class Panda:
    def __init__(self, name):
        self.name = name
        self._age = 1
        self.__weight = 100

    def _add_weight(self, kg):
        self.__weight += kg

    def eat(self, kg):
        if self.__weight < 1000:
            self._add_weight(kg)

Dunder Methods

  • Dunder comes from double under
  • Also known as "magic methods"
  • They override some aspects of the behavior of our objects
  • Examples:
    • ​__int__
    • __add__
    • __eq__
    • __lt__ / __gt__
    • __str__
    • __repr__
    • __has__
    • etc.

__str__ and __repr__

class Panda:
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight

    def __str__(self):
        return f'I am {self.name} panda.'
    
    def __repr__(self):
        return f'Panda {self.name} / {self.weight}'
>>> p = Panda('Marto', 100)
>>> p
Panda Marto / 100

>>> print(p)
I am Marto panda.

>>> f'Calling __str__ here: {p}'
'Calling __str__ here: I am Marto panda.'

Object Comparison

  • Use == to compare values
  • Use is  to compare if two objects are the same (references to two objects)
  • You can override __eq__ to handle custom equalization

Object Comparison

class Panda:
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight

    def __eq__(self, other):
        return self.weight == other.weight
>>> marto = Panda('Marto', 100)
>>> ivo = Panda('Ivo', 200)

>>> marto is ivo
False
>>> marto == ivo
False

>>> ivo.weight = 100
>>> marto == ivo
True
>>> marto is ivo
False

Object Comparison

>>> int1 = 100
>>> int2 = 100

>>> int1 is int2
True
>>> int1 == int2
True
>>> str1 = 'asd'
>>> str2 = 'asd'

>>> str1 is str2
True
>>> str1 == str2
True
>>> items1 = [1, 2, 3]
>>> items2 = [1, 2, 3]

>>> items1 is items2
False
>>> items1 == items2
True

Everything in Python is an object 

>>> type(100)
<class 'int'>

>>> type((100)) is int
True

>>> type((100,))
<class 'tuple'>

>>> type([])
<class 'list'>

>>> type([]) is list
True

>>> type(type(list))
<class 'type'>

>>> type(type)
<class 'type'>

Python 101 9th OOP part1

By Hack Bulgaria

Python 101 9th OOP part1

  • 1,018