4.1. OOP Principles¶
4.1.1. Rationale¶
Encapsulation
Abstraction
Inheritance
Polymorphism
4.1.2. Encapsulation¶
Do not allow to modify attributes directly
Hide them behind setters and getters
Prevents objects to get to an invalid state
class KelvinTemperature:
_value: float
def set_value(self, value: float) -> None:
if value >= 0:
self._value = value
def get_value(self) -> float:
return self._value
t = KelvinTemperature()
t.set_value(1)
t.set_value(0)
t.set_value(-1)
t.get_value()
class Astronaut:
_firstname: str
_lastname: str
def set_name(self, name):
fname, lname = name.split()
self._firstname = fname
self._lastname = lname
def get_name(self):
return f'{self._firstname} {self._lastname}'
astro = Astronaut()
astro.set_name('Mark Watney')
astro.get_name()
4.1.3. Abstraction¶
Reduce complexity by hiding unnecessary details
User do not need what does it mean to send email, that you have to connect, auth and later disconnect
class MailService:
def send_email(sender, rcpt, subject, body):
self._connect()
self._authenticate()
self._disconnect()
def _connect(self, timeout=1):
print('Connect')
def _authenticate(self):
print('Authenticate')
def _disconnect(self):
print('Disconnect')
if __name__ == '__main__':
ms = MailService()
ms.send_email(...)
4.1.4. Inheritance¶
class Person:
_firstname: str
_lastname: str
class Astronaut(Person):
pass
4.1.5. Polymorphism¶
Ability of an object to take many forms
from abc import ABCMeta, abstractmethod
class UIElement(metaclass=ABCMeta):
@abstractmethod
def draw(self):
pass
class TextBox(UIElement):
def draw(self):
print('Drawing text box')
class CheckBox(UIElement):
def draw(self):
print('Drawing check box')
def draw(element: UIElement):
element.draw()
if __name__ == '__main__':
draw(TextBox())
draw(CheckBox())
class Cache:
def set(self, name: str, value: str) -> None: pass
def get(self, name: str) -> str: pass
def is_valid(self, name: str) -> bool: pass
class DatabaseCache(Cache):
pass
class MemoryCache(Cache):
pass
class FilesystemCache(Cache):
pass
def get(cache: Cache, key):
if not cache.is_valid(key):
cache.set(key, '...')
return cache.get(key)
get(DatabaseCache(), 'name')
get(FilesystemCache(), 'name')
get(MemoryCache(), 'name')