├── .github └── FUNDING.yml ├── .gitignore ├── 01 - Introduction to OOP ├── README.md └── main.py ├── 02 - Constructor & __init__ ├── README.md └── main.py ├── 03 - Class Attributes ├── README.md ├── codesnippets │ └── five_items.py └── main.py ├── 04 - Class vs Static Methods ├── README.md ├── codesnippets │ └── items.csv ├── helper.py └── main.py ├── 05 - Class Inheritance ├── README.md └── main.py ├── 06 - Getters and Setters ├── item.py ├── items.csv ├── main.py └── phone.py ├── 07 - OOP Principles ├── item.py ├── items.csv ├── keyboard.py ├── main.py ├── phone.py └── poly_explain.py └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [jimdevops19] 2 | patreon: jimshapedcoding 3 | custom: ["https://www.buymeacoffee.com/jimsc"] 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /01 - Introduction to OOP/README.md: -------------------------------------------------------------------------------- 1 | # 01 - Introduction 2 | 3 | ## This is the First Episode for the OOP Course 4 | 5 | ### main.py file includes the code we have written till the end of the episode -------------------------------------------------------------------------------- /01 - Introduction to OOP/main.py: -------------------------------------------------------------------------------- 1 | # How to create a class: 2 | class Item: 3 | def calculate_total_price(self, x, y): 4 | return x * y 5 | 6 | # How to create an instance of a class 7 | item1 = Item() 8 | 9 | # Assign attributes: 10 | item1.name = "Phone" 11 | item1.price = 100 12 | item1.quantity = 5 13 | 14 | # Calling methods from instances of a class: 15 | print(item1.calculate_total_price(item1.price, item1.quantity)) 16 | 17 | # How to create an instance of a class (We could create as much as instances we'd like to) 18 | item2 = Item() 19 | 20 | # Assign attributes 21 | item2.name = "Laptop" 22 | item2.price = 1000 23 | item2.quantity = 3 24 | 25 | # Calling methods from instances of a class: 26 | print(item2.calculate_total_price(item2.price, item2.quantity)) -------------------------------------------------------------------------------- /02 - Constructor & __init__/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimdevops19/PythonOOP/69fc0d02cb8c21f7b1cbfdc3cdd718a4ada2a1d1/02 - Constructor & __init__/README.md -------------------------------------------------------------------------------- /02 - Constructor & __init__/main.py: -------------------------------------------------------------------------------- 1 | class Item: 2 | def __init__(self, name: str, price: float, quantity=0): 3 | # Run validations to the received arguments 4 | assert price >= 0, f"Price {price} is not greater than or equal to zero!" 5 | assert quantity >= 0, f"Quantity {quantity} is not greater or equal to zero!" 6 | 7 | # Assign to self object 8 | self.name = name 9 | self.price = price 10 | self.quantity = quantity 11 | 12 | def calculate_total_price(self): 13 | return self.price * self.quantity 14 | 15 | item1 = Item("Phone", 100, 1) 16 | item2 = Item("Laptop", 1000, 3) 17 | 18 | print(item1.calculate_total_price()) 19 | print(item2.calculate_total_price()) -------------------------------------------------------------------------------- /03 - Class Attributes/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimdevops19/PythonOOP/69fc0d02cb8c21f7b1cbfdc3cdd718a4ada2a1d1/03 - Class Attributes/README.md -------------------------------------------------------------------------------- /03 - Class Attributes/codesnippets/five_items.py: -------------------------------------------------------------------------------- 1 | item1 = Item("Phone", 100, 1) 2 | item2 = Item("Laptop", 1000, 3) 3 | item3 = Item("Cable", 10, 5) 4 | item4 = Item("Mouse", 50, 5) 5 | item5 = Item("Keyboard", 75, 5) -------------------------------------------------------------------------------- /03 - Class Attributes/main.py: -------------------------------------------------------------------------------- 1 | class Item: 2 | pay_rate = 0.8 # The pay rate after 20% discount 3 | all = [] 4 | def __init__(self, name: str, price: float, quantity=0): 5 | # Run validations to the received arguments 6 | assert price >= 0, f"Price {price} is not greater than or equal to zero!" 7 | assert quantity >= 0, f"Quantity {quantity} is not greater or equal to zero!" 8 | 9 | # Assign to self object 10 | self.name = name 11 | self.price = price 12 | self.quantity = quantity 13 | 14 | # Actions to execute 15 | Item.all.append(self) 16 | 17 | def calculate_total_price(self): 18 | return self.price * self.quantity 19 | 20 | def apply_discount(self): 21 | self.price = self.price * self.pay_rate 22 | 23 | def __repr__(self): 24 | return f"Item('{self.name}', {self.price}, {self.quantity})" 25 | 26 | item1 = Item("Phone", 100, 1) 27 | item2 = Item("Laptop", 1000, 3) 28 | item3 = Item("Cable", 10, 5) 29 | item4 = Item("Mouse", 50, 5) 30 | item5 = Item("Keyboard", 75, 5) 31 | 32 | print(Item.all) -------------------------------------------------------------------------------- /04 - Class vs Static Methods/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimdevops19/PythonOOP/69fc0d02cb8c21f7b1cbfdc3cdd718a4ada2a1d1/04 - Class vs Static Methods/README.md -------------------------------------------------------------------------------- /04 - Class vs Static Methods/codesnippets/items.csv: -------------------------------------------------------------------------------- 1 | name,price,quantity 2 | "Phone",100,1 3 | "Laptop",1000,3 4 | "Cable",10,5 5 | "Mouse",50,5 6 | "Keyboard",75,5 7 | -------------------------------------------------------------------------------- /04 - Class vs Static Methods/helper.py: -------------------------------------------------------------------------------- 1 | # When to use class methods and when to use static methods ? 2 | 3 | class Item: 4 | @staticmethod 5 | def is_integer(): 6 | ''' 7 | This should do something that has a relationship 8 | with the class, but not something that must be unique 9 | per instance! 10 | ''' 11 | @classmethod 12 | def instantiate_from_something(cls): 13 | ''' 14 | This should also do something that has a relationship 15 | with the class, but usually, those are used to 16 | manipulate different structures of data to instantiate 17 | objects, like we have done with CSV. 18 | ''' 19 | 20 | # THE ONLY DIFFERENCE BETWEEN THOSE: 21 | # Static methods are not passing the object reference as the first argument in the background! 22 | 23 | 24 | # NOTE: However, those could be also called from instances. 25 | 26 | item1 = Item() 27 | item1.is_integer() 28 | item1.instantiate_from_something() -------------------------------------------------------------------------------- /04 - Class vs Static Methods/main.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | 4 | class Item: 5 | pay_rate = 0.8 # The pay rate after 20% discount 6 | all = [] 7 | def __init__(self, name: str, price: float, quantity=0): 8 | # Run validations to the received arguments 9 | assert price >= 0, f"Price {price} is not greater than or equal to zero!" 10 | assert quantity >= 0, f"Quantity {quantity} is not greater or equal to zero!" 11 | 12 | # Assign to self object 13 | self.name = name 14 | self.price = price 15 | self.quantity = quantity 16 | 17 | # Actions to execute 18 | Item.all.append(self) 19 | 20 | def calculate_total_price(self): 21 | return self.price * self.quantity 22 | 23 | def apply_discount(self): 24 | self.price = self.price * self.pay_rate 25 | 26 | @classmethod 27 | def instantiate_from_csv(cls): 28 | with open('items.csv', 'r') as f: 29 | reader = csv.DictReader(f) 30 | items = list(reader) 31 | 32 | for item in items: 33 | Item( 34 | name=item.get('name'), 35 | price=float(item.get('price')), 36 | quantity=int(item.get('quantity')), 37 | ) 38 | 39 | @staticmethod 40 | def is_integer(num): 41 | # We will count out the floats that are point zero 42 | # For i.e: 5.0, 10.0 43 | if isinstance(num, float): 44 | # Count out the floats that are point zero 45 | return num.is_integer() 46 | elif isinstance(num, int): 47 | return True 48 | else: 49 | return False 50 | 51 | def __repr__(self): 52 | return f"Item('{self.name}', {self.price}, {self.quantity})" -------------------------------------------------------------------------------- /05 - Class Inheritance/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimdevops19/PythonOOP/69fc0d02cb8c21f7b1cbfdc3cdd718a4ada2a1d1/05 - Class Inheritance/README.md -------------------------------------------------------------------------------- /05 - Class Inheritance/main.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | 4 | class Item: 5 | pay_rate = 0.8 # The pay rate after 20% discount 6 | all = [] 7 | def __init__(self, name: str, price: float, quantity=0): 8 | # Run validations to the received arguments 9 | assert price >= 0, f"Price {price} is not greater than or equal to zero!" 10 | assert quantity >= 0, f"Quantity {quantity} is not greater or equal to zero!" 11 | 12 | # Assign to self object 13 | self.name = name 14 | self.price = price 15 | self.quantity = quantity 16 | 17 | # Actions to execute 18 | Item.all.append(self) 19 | 20 | def calculate_total_price(self): 21 | return self.price * self.quantity 22 | 23 | def apply_discount(self): 24 | self.price = self.price * self.pay_rate 25 | 26 | @classmethod 27 | def instantiate_from_csv(cls): 28 | with open('items.csv', 'r') as f: 29 | reader = csv.DictReader(f) 30 | items = list(reader) 31 | 32 | for item in items: 33 | Item( 34 | name=item.get('name'), 35 | price=float(item.get('price')), 36 | quantity=int(item.get('quantity')), 37 | ) 38 | 39 | @staticmethod 40 | def is_integer(num): 41 | # We will count out the floats that are point zero 42 | # For i.e: 5.0, 10.0 43 | if isinstance(num, float): 44 | # Count out the floats that are point zero 45 | return num.is_integer() 46 | elif isinstance(num, int): 47 | return True 48 | else: 49 | return False 50 | 51 | def __repr__(self): 52 | return f"{self.__class__.__name__}('{self.name}', {self.price}, {self.quantity})" 53 | 54 | 55 | class Phone(Item): 56 | def __init__(self, name: str, price: float, quantity=0, broken_phones=0): 57 | # Call to super function to have access to all attributes / methods 58 | super().__init__( 59 | name, price, quantity 60 | ) 61 | 62 | # Run validations to the received arguments 63 | assert broken_phones >= 0, f"Broken Phones {broken_phones} is not greater or equal to zero!" 64 | 65 | # Assign to self object 66 | self.broken_phones = broken_phones 67 | 68 | phone1 = Phone("jscPhonev10", 500, 5, 1) 69 | 70 | print(Item.all) -------------------------------------------------------------------------------- /06 - Getters and Setters/item.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | 4 | class Item: 5 | pay_rate = 0.8 # The pay rate after 20% discount 6 | all = [] 7 | def __init__(self, name: str, price: float, quantity=0): 8 | # Run validations to the received arguments 9 | assert price >= 0, f"Price {price} is not greater than or equal to zero!" 10 | assert quantity >= 0, f"Quantity {quantity} is not greater or equal to zero!" 11 | 12 | # Assign to self object 13 | self.__name = name 14 | self.price = price 15 | self.quantity = quantity 16 | 17 | # Actions to execute 18 | Item.all.append(self) 19 | 20 | @property 21 | # Property Decorator = Read-Only Attribute 22 | def name(self): 23 | return self.__name 24 | 25 | @name.setter 26 | def name(self, value): 27 | if len(value) > 10: 28 | raise Exception("The name is too long!") 29 | else: 30 | self.__name = value 31 | 32 | def calculate_total_price(self): 33 | return self.price * self.quantity 34 | 35 | def apply_discount(self): 36 | self.price = self.price * self.pay_rate 37 | 38 | @classmethod 39 | def instantiate_from_csv(cls): 40 | with open('items.csv', 'r') as f: 41 | reader = csv.DictReader(f) 42 | items = list(reader) 43 | 44 | for item in items: 45 | Item( 46 | name=item.get('name'), 47 | price=float(item.get('price')), 48 | quantity=int(item.get('quantity')), 49 | ) 50 | 51 | @staticmethod 52 | def is_integer(num): 53 | # We will count out the floats that are point zero 54 | # For i.e: 5.0, 10.0 55 | if isinstance(num, float): 56 | # Count out the floats that are point zero 57 | return num.is_integer() 58 | elif isinstance(num, int): 59 | return True 60 | else: 61 | return False 62 | 63 | def __repr__(self): 64 | return f"{self.__class__.__name__}('{self.name}', {self.price}, {self.quantity})" -------------------------------------------------------------------------------- /06 - Getters and Setters/items.csv: -------------------------------------------------------------------------------- 1 | name,price,quantity 2 | "Phone",100,1 3 | "Laptop",1000,3 4 | "Cable",10,5 5 | "Mouse",50,5 6 | "Keyboard",74.90,5 7 | -------------------------------------------------------------------------------- /06 - Getters and Setters/main.py: -------------------------------------------------------------------------------- 1 | from item import Item 2 | 3 | item1 = Item("MyItem", 750) 4 | 5 | # Setting an Attribute 6 | item1.name = "OtherItem" 7 | 8 | # Getting an Attribute 9 | print(item1.name) -------------------------------------------------------------------------------- /06 - Getters and Setters/phone.py: -------------------------------------------------------------------------------- 1 | from item import Item 2 | 3 | 4 | class Phone(Item): 5 | def __init__(self, name: str, price: float, quantity=0, broken_phones=0): 6 | # Call to super function to have access to all attributes / methods 7 | super().__init__( 8 | name, price, quantity 9 | ) 10 | 11 | # Run validations to the received arguments 12 | assert broken_phones >= 0, f"Broken Phones {broken_phones} is not greater or equal to zero!" 13 | 14 | # Assign to self object 15 | self.broken_phones = broken_phones -------------------------------------------------------------------------------- /07 - OOP Principles/item.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | 4 | class Item: 5 | pay_rate = 0.8 # The pay rate after 20% discount 6 | all = [] 7 | def __init__(self, name: str, price: float, quantity=0): 8 | # Run validations to the received arguments 9 | assert price >= 0, f"Price {price} is not greater than or equal to zero!" 10 | assert quantity >= 0, f"Quantity {quantity} is not greater or equal to zero!" 11 | 12 | # Assign to self object 13 | self.__name = name 14 | self.__price = price 15 | self.quantity = quantity 16 | 17 | # Actions to execute 18 | Item.all.append(self) 19 | 20 | @property 21 | def price(self): 22 | return self.__price 23 | 24 | def apply_discount(self): 25 | self.__price = self.__price * self.pay_rate 26 | 27 | def apply_increment(self, increment_value): 28 | self.__price = self.__price + self.__price * increment_value 29 | 30 | @property 31 | def name(self): 32 | # Property Decorator = Read-Only Attribute 33 | return self.__name 34 | 35 | @name.setter 36 | def name(self, value): 37 | if len(value) > 10: 38 | raise Exception("The name is too long!") 39 | else: 40 | self.__name = value 41 | 42 | def calculate_total_price(self): 43 | return self.__price * self.quantity 44 | 45 | @classmethod 46 | def instantiate_from_csv(cls): 47 | with open('items.csv', 'r') as f: 48 | reader = csv.DictReader(f) 49 | items = list(reader) 50 | 51 | for item in items: 52 | Item( 53 | name=item.get('name'), 54 | price=float(item.get('price')), 55 | quantity=int(item.get('quantity')), 56 | ) 57 | 58 | @staticmethod 59 | def is_integer(num): 60 | # We will count out the floats that are point zero 61 | # For i.e: 5.0, 10.0 62 | if isinstance(num, float): 63 | # Count out the floats that are point zero 64 | return num.is_integer() 65 | elif isinstance(num, int): 66 | return True 67 | else: 68 | return False 69 | 70 | def __repr__(self): 71 | return f"{self.__class__.__name__}('{self.name}', {self.__price}, {self.quantity})" 72 | 73 | -------------------------------------------------------------------------------- /07 - OOP Principles/items.csv: -------------------------------------------------------------------------------- 1 | name,price,quantity 2 | "Phone",100,1 3 | "Laptop",1000,3 4 | "Cable",10,5 5 | "Mouse",50,5 6 | "Keyboard",74.90,5 7 | -------------------------------------------------------------------------------- /07 - OOP Principles/keyboard.py: -------------------------------------------------------------------------------- 1 | from item import Item 2 | 3 | 4 | class Keyboard(Item): 5 | pay_rate = 0.7 6 | def __init__(self, name: str, price: float, quantity=0): 7 | # Call to super function to have access to all attributes / methods 8 | super().__init__( 9 | name, price, quantity 10 | ) -------------------------------------------------------------------------------- /07 - OOP Principles/main.py: -------------------------------------------------------------------------------- 1 | from phone import Phone 2 | from keyboard import Keyboard 3 | 4 | item1 = Keyboard("jscKeyboard", 1000, 3) 5 | 6 | item1.apply_discount() 7 | 8 | print(item1.price) -------------------------------------------------------------------------------- /07 - OOP Principles/phone.py: -------------------------------------------------------------------------------- 1 | from item import Item 2 | 3 | 4 | class Phone(Item): 5 | pay_rate = 0.5 6 | def __init__(self, name: str, price: float, quantity=0, broken_phones=0): 7 | # Call to super function to have access to all attributes / methods 8 | super().__init__( 9 | name, price, quantity 10 | ) 11 | 12 | # Run validations to the received arguments 13 | assert broken_phones >= 0, f"Broken Phones {broken_phones} is not greater or equal to zero!" 14 | 15 | # Assign to self object 16 | self.broken_phones = broken_phones -------------------------------------------------------------------------------- /07 - OOP Principles/poly_explain.py: -------------------------------------------------------------------------------- 1 | name = "Jim" # str 2 | print(len(name)) 3 | 4 | some_list = ["some","name"] # list 5 | print(len(some_list)) 6 | # That's polymorphism in action, a single function does now 7 | # how to handle different kinds of objects as expected! -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PythonOOP 2 | The Original Code repository for my Python OOP Series 3 | --------------------------------------------------------------------------------