Last active
April 15, 2023 17:36
-
-
Save mahenzon/4716d793c11a3dedda01f83404a6d115 to your computer and use it in GitHub Desktop.
SOLID Principles Python examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# SOLID Principles example\n", | |
"\n", | |
"\n", | |
"## 1. Single Responsibility Principle\n", | |
"\n", | |
"\n", | |
"### 1.1 Single Responsibility Principle violation\n", | |
"\n", | |
"```python\n", | |
"class Animal:\n", | |
" def __init__(self, name):\n", | |
" self.name = name\n", | |
"\n", | |
" def make_sound(self):\n", | |
" print(self.name, \"makes sound...\")\n", | |
"\n", | |
" @classmethod\n", | |
" def get_from_db(cls, name):\n", | |
" print(\"find\", name, \"in db\", cls)\n", | |
"\n", | |
" def save_to_db(self):\n", | |
" print(\"save to db\", self)\n", | |
"```\n", | |
"\n", | |
"\n", | |
"### 1.2 Following the Single Responsibility Principle\n", | |
"\n", | |
"\n", | |
"```python\n", | |
"class Animal:\n", | |
" def __init__(self, name):\n", | |
" self.name = name\n", | |
"\n", | |
" def make_sound(self):\n", | |
" print(self.name, \"makes sound...\")\n", | |
"\n", | |
"\n", | |
"class AnimalDB:\n", | |
"\n", | |
" @classmethod\n", | |
" def get_from_db(cls, name):\n", | |
" print(\"find\", name, \"in db\", cls)\n", | |
"\n", | |
" @classmethod\n", | |
" def save_to_db(cls, animal):\n", | |
" print(\"save to db\", animal)\n", | |
"```\n", | |
"\n", | |
"\n", | |
"## 2. Open Closed Principle\n", | |
"\n", | |
"\n", | |
"### 2.1 Open Closed Principle violation\n", | |
"\n", | |
"```python\n", | |
"def get_animal_sound(animal):\n", | |
" if animal.name == \"lion\":\n", | |
" return \"roar\"\n", | |
" if animal.name == \"cat\":\n", | |
" return \"meow\"\n", | |
"```\n", | |
"\n", | |
"### 2.2 Following the Open Closed Principle\n", | |
"\n", | |
"```python\n", | |
"class Animal:\n", | |
" def __init__(self, name, sound):\n", | |
" self.name = name\n", | |
" self.sound = sound\n", | |
" \n", | |
" def make_sound(self):\n", | |
" print(self.name, \"makes sound\", self.sound)\n", | |
" \n", | |
"\n", | |
"lion = Animal(\"lion\", \"roar\")\n", | |
"cat = Animal(\"cat\", \"meow\")\n", | |
"print(lion.sound)\n", | |
"# roar\n", | |
"lion.make_sound()\n", | |
"# lion makes sound roar\n", | |
"print(cat.sound)\n", | |
"# meow\n", | |
"cat.make_sound()\n", | |
"# cat makes sound meow\n", | |
"```\n", | |
"\n", | |
"\n", | |
"## 3. Liskov Substitution Principle\n", | |
"\n", | |
"\n", | |
"### 3.1 Liskov Substitution Principle violation\n", | |
"\n", | |
"```python\n", | |
"def get_animal_tail_info(animal):\n", | |
" if isinstance(animal, Lion):\n", | |
" return animal.get_lion_tail_info()\n", | |
" if isinstance(animal, Cat):\n", | |
" return animal.get_cat_tail_info()\n", | |
"```\n", | |
"\n", | |
"### 3.2 Following the Liskov Substitution Principle\n", | |
"\n", | |
"\n", | |
"```python\n", | |
"class Animal:\n", | |
" def get_tail_info(self):\n", | |
" return \"\"\n", | |
"\n", | |
"\n", | |
"class Lion(Animal):\n", | |
" def get_tail_info(self):\n", | |
" return \"Lion has a big and heavy tail...\"\n", | |
"\n", | |
"\n", | |
"class Cat(Animal):\n", | |
" def get_tail_info(self):\n", | |
" return \"Cat has a nice and furry tail...\"\n", | |
"\n", | |
"\n", | |
"def get_animal_tail_info(animal: Animal):\n", | |
" return animal.get_tail_info()\n", | |
"```\n", | |
"\n", | |
"\n", | |
"## 4. Interface Segregation Principle\n", | |
"\n", | |
"\n", | |
"### 4.1 Following the Interface Segregation Principle\n", | |
"\n", | |
"\n", | |
"```python\n", | |
"from abc import abstractmethod\n", | |
"\n", | |
"\n", | |
"class MessagingDevice:\n", | |
"\n", | |
" @abstractmethod\n", | |
" def send_email(self, recipient, email_object):\n", | |
" pass\n", | |
"\n", | |
" @abstractmethod\n", | |
" def send_sms(self, recipient, sms_object):\n", | |
" pass\n", | |
"\n", | |
"\n", | |
"class Smartphone(MessagingDevice):\n", | |
" \"\"\"\n", | |
" Just a regular smartphone\n", | |
" \"\"\"\n", | |
"\n", | |
" def send_email(self, recipient, email_object):\n", | |
" print(self, \"send email\", email_object, \"to\", recipient)\n", | |
"\n", | |
" def send_sms(self, recipient, sms_object):\n", | |
" print(self, \"send sms\", sms_object, \"to\", recipient)\n", | |
"\n", | |
"\n", | |
"class PDA(MessagingDevice):\n", | |
" \"\"\"\n", | |
" A personal digital assistant (PDA),\n", | |
" also known as a handheld PC\n", | |
" \"\"\"\n", | |
"\n", | |
" def send_email(self, recipient, email_object):\n", | |
" print(self, \"send email\", email_object, \"to\", recipient)\n", | |
"\n", | |
" def send_sms(self, recipient, sms_object):\n", | |
" print(self, \"send sms\", sms_object, \"to\", recipient)\n", | |
"```\n", | |
"\n", | |
"\n", | |
"\n", | |
"## 5. Dependency Inversion Principle\n", | |
"\n", | |
"\n", | |
"### 5.1 Dependency Inversion Principle violation\n", | |
"\n", | |
"```python\n", | |
"class LightBulb:\n", | |
" def turn_on(self):\n", | |
" print(\"LightBulb turned on\")\n", | |
"\n", | |
" def turn_off(self):\n", | |
" print(\"LightBulb turned off\")\n", | |
"\n", | |
"\n", | |
"class PowerSwitch:\n", | |
" def __init__(self, light_bulb: LightBulb):\n", | |
" self.light_bulb = light_bulb\n", | |
" self.on = False\n", | |
"\n", | |
" def toggle(self):\n", | |
" if self.on:\n", | |
" self.light_bulb.turn_off()\n", | |
" self.on = False\n", | |
" else:\n", | |
" self.light_bulb.turn_on()\n", | |
" self.on = True\n", | |
"```\n", | |
"\n", | |
"### 5.2 Following the Dependency Inversion Principle\n", | |
"\n", | |
"\n", | |
"```python\n", | |
"\n", | |
"# Creating an abstraction\n", | |
"\n", | |
"from abc import abstractmethod\n", | |
"\n", | |
"\n", | |
"class Switchable:\n", | |
" @abstractmethod\n", | |
" def turn_on(self):\n", | |
" pass\n", | |
"\n", | |
" @abstractmethod\n", | |
" def turn_off(self):\n", | |
" pass\n", | |
"\n", | |
"\n", | |
"# Implementing the Switchable interface\n", | |
"\n", | |
"class LightBulb(Switchable):\n", | |
" def turn_on(self):\n", | |
" print(\"LightBulb turned on\")\n", | |
"\n", | |
" def turn_off(self):\n", | |
" print(\"LightBulb turned off\")\n", | |
"\n", | |
"\n", | |
"class PowerSwitch:\n", | |
" def __init__(self, client: Switchable):\n", | |
" if not isinstance(client, Switchable):\n", | |
" raise TypeError(\"expected Switchable, got\", client)\n", | |
"\n", | |
" self.client = client\n", | |
" self.on = False\n", | |
"\n", | |
" def toggle(self):\n", | |
" if self.on:\n", | |
" self.client.turn_off()\n", | |
" self.on = False\n", | |
" else:\n", | |
" self.client.turn_on()\n", | |
" self.on = True\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"outputs": [], | |
"source": [], | |
"metadata": { | |
"collapsed": false | |
} | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3 (ipykernel)", | |
"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": 1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment