Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions workspace/3_oops/10_exception.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Exception: An event that interrupts the normal flow of the program's execution.
# ZeroDivisionError: Occurs when you try to divide by zero.
# SyntaxError: Occurs when Python encounters incorrect syntax.
# TypeError: Occurs when you try to combine two objects that are not compatible.
# ValueError: Occurs when a built-in operation or function receives an argument that has the right type but an inappropriate value.
#
# 1. try:, 2. except:, 3. else:, 4. finally:

try:
number = int(input("Enter a number: "))
print(1/number)
except ZeroDivisionError:
print("You can't divide by zero.")
except ValueError:
print("Please enter a valid number.")
except Exception:
print("Something went wrong.")
finally:
print("This will always run.")
16 changes: 16 additions & 0 deletions workspace/3_oops/11_1_file_detection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Python file detection

import os

# file_path = "workspace/3_oops/test.txt"
file_path = "workspace/3_oops"

if os.path.exists(file_path):
print(f"File exists in {file_path}.")

if os.path.isfile(file_path):
print(f"File is a regular file.")
elif os.path.isdir(file_path):
print(f"File is a directory.")
else:
print(f"File does not exist in {file_path}.")
70 changes: 70 additions & 0 deletions workspace/3_oops/11_2_file_writing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Python write to files (.txt, .csv, .json)

import csv
import json


text_data = "Hello, World!"

file_path = "workspace/3_oops/output.txt"
xfile_path = "workspace/3_oops/output_x.txt"
employees = ["John", "Doe", "Jane", "Doe"]

# w: write, a: append, r: read, x: create
with open(file_path, "w") as file:
file.write(text_data)
print(f"Data written to {file_path}.")

try:
with open(xfile_path, "x") as file:
file.write(text_data)
print(f"Data written to {xfile_path}.")
except FileExistsError:
print(f"File already exists in {xfile_path}.")

try:
with open(file_path, "a") as file:
file.write("\n" +text_data)
print(f"Data written to {file_path}.")
for employee in employees:
file.write("\n" +employee)
except FileExistsError:
print(f"File already exists in {file_path}.")


#JSON

jfile_path = "workspace/3_oops/output.json"

student = {
"name": "John Doe",
"age": 25,
"grade": "A"
}

try:
with open(jfile_path, "w") as file:
json.dump(student, file, indent=4)
print(f"JSON Data written to {jfile_path}.")
except FileExistsError:
print(f"File already exists in {jfile_path}.")

# CSV

students = [["Name", "Age", "Grade"],
["John Doe", 25, "A"],
["Jane Doe", 24, "B"],
["Jim Doe", 23, "C"],
["Jill Doe", 22, "D"]]

cfile_path = "workspace/3_oops/output.csv"

try:
with open(cfile_path, "w", newline="") as file:
writer = csv.writer(file)
for row in students:
writer.writerow(row)
print(f"CSV Data written to {cfile_path}.")

except FileExistsError:
print(f"File already exists in {cfile_path}.")
59 changes: 59 additions & 0 deletions workspace/3_oops/11_3_file_read.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Python reading files (.txt, .csv, .json)

import csv
import json


file_path = 'workspace/3_oops/output.txt'
nfile_path = 'workspace/3_oops/no-exists.txt'

# r= read, w= write, a= append, r+= read and write
with open(file_path, 'r') as file:
content = file.read()
print(content)

try:
with open(nfile_path, 'r') as file:
content = file.read()
print(content)
except FileNotFoundError:
print('File not found')

try:
with open(file_path, 'r') as file:
content = file.read()
print(content)
except FileNotFoundError:
print('File not found')
except PermissionError:
print('Permission denied')

# JSON
jfile_path = 'workspace/3_oops/output.json'

try:
with open(jfile_path, 'r') as file:
content = json.load(file)
print(content)
print(content['name'])
except FileNotFoundError:
print('File not found')
except PermissionError:
print('Permission denied')


# CSV
cfile_path = 'workspace/3_oops/output.csv'

try:
with open(cfile_path, 'r') as file:
content = csv.reader(file)
for line in content:
print(line)
print(line[0])
print(line[1])
except FileNotFoundError:
print('File not found')
except PermissionError:
print('Permission denied')

27 changes: 27 additions & 0 deletions workspace/3_oops/12_datetime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Python system datetime module
import datetime

date = datetime.date(2025, 10, 31)
today = datetime.date.today()


print(date) # 2025-10-31
print(today) # 2025-01-01


time = datetime.time(23, 59, 59)
now = datetime.datetime.now()

nowFormatted = now.strftime("%H:%M:%S %d-%m-%Y")

print(time) # 23:59:59
print(now) # 2025-01-01 16:49:18.910042
print(nowFormatted) # 16:49:18 2025-01-01

target_datetime = datetime.datetime(2025, 10, 31, 23, 59, 59)
current_datetime = datetime.datetime.now()

if target_datetime < current_datetime:
print("Target datetime has passed")
else:
print("Target datetime has not passed")
40 changes: 40 additions & 0 deletions workspace/3_oops/6_class_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Class method: Allowing access to the class from the instance
# Take (cls/self) as the first argument, which represents the class itself
#
# Instance method: Best for operations on instance of the class (object)
# Static method: Best for utility functions, which do not require access to the class or instance
# Class method: Best for class-level operations, which require access to the class, but not the instance

class Employee:

num_of_emps = 0
total_pay = 0

def __init__(self, name, pay):
self.name = name
self.pay = pay
self.email = name + '@company.com'
Employee.num_of_emps += 1
Employee.total_pay += pay

# Instance method
def get_info(self):
return (f"{self.name}: {self.pay}")

@classmethod
def get_num_of_emps(cls):
return (f"Total # of employees: {cls.num_of_emps}")

@classmethod
def get_avg_pay(cls):
if cls.num_of_emps == 0:
return 0

return f"Average pay: {cls.total_pay / cls.num_of_emps:0.2f}"

emp1 = Employee('Doe', 6000)
emp2 = Employee('John', 5000)
emp3 = Employee('Jane', 7000)

print(Employee.get_num_of_emps())
print(Employee.get_avg_pay())
61 changes: 61 additions & 0 deletions workspace/3_oops/7_magic(dunder)_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Magic methods: dunder/double underscore methods
# __init__, __str__, __eq__
# These methods are called automatically when certain operations are performed on objects.
# Allow developers to define custom behavior for objects.

class Book:

def __init__(self, title, author, pages):
self.title = title
self.author = author
self.pages = pages

def __str__(self):
return (f"'{self.title}' by {self.author}")

def __eq__(self, other):
return self.title == other.title and self.author == other.author

def __lt__(self, other):
return self.pages < other.pages

def __gt__(self, other):
return self.pages > other.pages

def __add__(self, other):
return f"{self.pages + other.pages} pages"

def __contains__(self, keyword):
return keyword in self.title or keyword in self.author

def __getitem__(self, key):
if key == 'title':
return self.title
elif key == 'author':
return self.author
elif key == 'pages':
return self.pages
else:
return f"Invalid key: {key}"

book1 = Book('Python', 'John Doe', 210)
book2 = Book('Python', 'John Doe', 210)
# book2 = Book('Java', 'Jane Doe', 330)
book3 = Book('PHP', 'Hacker', 192)

# __str__ method is called automatically when we print the object instead memory address is printed.
print(book1)
print(book2)
print(book3)

# __eq__ method is called automatically when we compare two objects.
print(book1 == book2)
print(book2 < book3)
print(book2 > book3)
print(book2 + book3)

print("PHP" in book3)
print("John" in book1)

print(book1['title'])
print(book1['audio'])
59 changes: 59 additions & 0 deletions workspace/3_oops/8_@property.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# @property
# @property is a built-in decorator in Python which is helpful in defining the properties effortlessly without calling the property() function explicitly.
# Decorator used to dfine a method as a property. (it can be accessed as an attribute instead of a method)
# Benefits:
# - Add additional logic when read, write or delete a property
# - gives you getter, setter, deleter methods

class Reactangle:
def __init__(self, width, height):
# _width and _height are private variables, they are not accessible from outside the class
self._width = width
self._height = height

# Getter
@property
def width(self):
return f"{self._width:.1f}cm"

@property
def height(self):
return f"{self._height:.1f}cm"

# Setter
@width.setter
def width(self, new_width):
if new_width > 0:
self._width = new_width
else:
print("Width must be greater than 0")

@height.setter
def height(self, new_height):
if new_height > 0:
self._height = new_height
else:
print("Height must be greater than 0")


# Deleter
@width.deleter
def width(self):
del self._width
print("Width has been deleted")

@height.deleter
def height(self):
del self._height
print("Height has been deleted")

rectangle = Reactangle(10, 20)

rectangle.width = 40
rectangle.height = 70

del rectangle.width
del rectangle.height

# print(rectangle.width)
# print(rectangle.height)
26 changes: 26 additions & 0 deletions workspace/3_oops/9_decorator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Decorator: A function that takes another function as an argument and adds some kind of functionality and returns another function
# without altering the source code of the original function that is passed as an argument.
# Pass the base function as an argument to the decorator function and return the modified function.
#
# @add_sprinkles
# get_icecream("Vanilla")

def add_sprinkles(func):
# wrapper function is needed to avoid calling the function directly
def wrapper(*args, **kwargs):
print(f"*Adding sprinkles 🎉*")
func(*args, **kwargs)
return wrapper

def add_fudge(func):
def wrapper(*args, **kwargs):
print(f"*Adding fudge 🍫*")
func(*args, **kwargs)
return wrapper

@add_sprinkles
@add_fudge
def get_icecream(flavor):
print(f"Here is your {flavor} icecream 🍦")

get_icecream("Vanilla")
Loading