Model and Object Oriented Programming Notes
Programming with Python classes.
Terminology
Object-Oriented Programming (OOP) uses classes as blueprints for creating Objects. Classes have Attributes assigned to the object with the keyword self
and Methods specific to the object.
Additional info:
- an Object is an Instance of the Class/Template
- there can be many Objects created from the same Class
- each Object contains its own Instance Data
- the data is setup by the Constructor, this is the "init" method in a Python class
- all methods in the Class/Template become part of the Object, methods are accessed using dot notation (object.method())
The Initial Code
This is the code provided to us as an example.
# A gateway in necessary as a web server cannot communicate directly with Python.
# In this case, imports are focused on generating hash code to protect passwords.
from werkzeug.security import generate_password_hash, check_password_hash
import json
# Define a User Class/Template
# -- A User represents the data we want to manage
class User:
# constructor of a User object, initializes the instance variables within object (self)
def __init__(self, name, uid, password):
self._name = name # variables with self prefix become part of the object,
self._uid = uid
self.set_password(password)
# a name getter method, extracts name from object
@property
def name(self):
return self._name
# a setter function, allows name to be updated after initial object creation
@name.setter
def name(self, name):
self._name = name
# a getter method, extracts email from object
@property
def uid(self):
return self._uid
# a setter function, allows name to be updated after initial object creation
@uid.setter
def uid(self, uid):
self._uid = uid
# check if uid parameter matches user id in object, return boolean
def is_uid(self, uid):
return self._uid == uid
@property
def password(self):
return self._password[0:10] + "..." # because of security only show 1st characters
# update password, this is conventional setter
def set_password(self, password):
"""Create a hashed password."""
self._password = generate_password_hash(password, method='sha256')
# check password parameter versus stored/encrypted password
def is_password(self, password):
"""Check against hashed password."""
result = check_password_hash(self._password, password)
return result
# output content using str(object) in human readable form, uses getter
def __str__(self):
return f'name: "{self.name}", id: "{self.uid}", psw: "{self.password}"'
# output command to recreate the object, uses attribute directly
def __repr__(self):
return f'Person(name={self._name}, uid={self._uid}, password={self._password})'
# tester method to print users
def tester(users, uid, psw):
result = None
for user in users:
# test for match in database
if user.uid == uid and user.is_password(psw): # check for match
print("* ", end="")
result = user
# print using __str__ method
print(str(user))
return result
# place tester code inside of special if! This allows include without tester running
if __name__ == "__main__":
# define user objects
u1 = User(name='Thomas Edison', uid='toby', password='123toby')
u2 = User(name='Nicholas Tesla', uid='nick', password='123nick')
u3 = User(name='Alexander Graham Bell', uid='lex', password='123lex')
u4 = User(name='Eli Whitney', uid='eli', password='123eli')
u5 = User(name='Hedy Lemarr', uid='hedy', password='123hedy')
# put user objects in list for convenience
users = [u1, u2, u3, u4, u5]
# Find user
print("Test 1, find user 3")
u = tester(users, u3.uid, "123lex")
# Change user
print("Test 2, change user 3")
u.name = "John Mortensen"
u.uid = "jm1021"
u.set_password("123qwerty")
u = tester(users, u.uid, "123qwerty")
# Make dictionary
'''
The __dict__ in Python represents a dictionary or any mapping object that is used to store the attributes of the object.
Every object in Python has an attribute that is denoted by __dict__.
Use the json.dumps() method to convert the list of Users to a JSON string.
'''
print("Test 3, make a dictionary")
json_string = json.dumps([user.__dict__ for user in users])
print(json_string)
print("Test 4, make a dictionary")
json_string = json.dumps([vars(user) for user in users])
print(json_string)
from datetime import date
#old code comments deleted to de-clutter; you can see them above
class User:
def __init__(self, name, uid, password, classOf, dob):
self._name = name
self._uid = uid
self.set_password(password)
self._classOf = classOf
self._dob = dob
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
@property
def uid(self):
return self._uid
@uid.setter
def uid(self, uid):
self._uid = uid
def is_uid(self, uid):
return self._uid == uid
@property
def password(self):
return self._password[0:10] + "..." # because of security only show 1st characters
def set_password(self, password):
"""Create a hashed password."""
self._password = generate_password_hash(password, method='sha256')
def is_password(self, password):
"""Check against hashed password."""
result = check_password_hash(self._password, password)
return result
def __str__(self):
return f'name: "{self.name}", id: "{self.uid}", psw: "{self.password}"'
def __repr__(self):
return f'Person(name={self._name}, uid={self._uid}, password={self._password})'
#here's the classOf getter
@property
def classOf(self):
return self._classOf
#here's the classOf setter
@classOf.setter
def classOf(self, classOf):
self._classOf = classOf
#here's the date of birth getter
@property
def dob(self):
return self._dob
#here's the date of birth setter
@dob.setter
def dob(self, dob):
self._dob = dob
# tester method to print users
def tester(users, uid, psw):
result = None
for user in users:
# test for match in database
if user.uid == uid and user.is_password(psw): # check for match
print("* ", end="")
result = user
# print using __str__ method
print(str(user))
return result
# NEW: AGE CALCULATOR (from provided template)
def calculate_age(dob):
today = date.today()
return today.year - dob.year - ((today.month, today.day) < (dob.month, dob.day))
if __name__ == "__main__":
# defining user objects again
u1 = User(name='Thomas Edison', uid='toby', password='123toby', classOf='1865', dob=(1847, 2, 11))
u2 = User(name='Nicholas Tesla', uid='nick', password='123nick', classOf='1874', dob=(1856, 7, 10))
u3 = User(name='Alexander Graham Bell', uid='lex', password='123lex', classOf='1865', dob=(1847, 3, 3))
u4 = User(name='Eli Whitney', uid='eli', password='123eli', classOf='1783', dob=(1765, 12, 8))
u5 = User(name='Hedy Lemarr', uid='hedy', password='123hedy', classOf='1932', dob=(1917, 11, 9))
users = [u1, u2, u3, u4, u5]
#HERE IS THE START OF MY UNIQUE TESTS
print("Test 5, find the oldest user")
agelist = []
for user in users:
tempdob = date(user._dob[0], user._dob[1], user._dob[2])
age = calculate_age(tempdob)
agelist.append(age)
max_age = max(agelist)
for index, item in enumerate(agelist):
if item == max_age:
oldest = index
for index, user in enumerate(users):
if index == oldest:
print("* ", end="")
print(user._name + ":", agelist[index], "years old.")
print("Test 6, show user graduation dates")
for user in users:
print(user.name, "graduated in", user.classOf + ".")
dob = date(2004, 12, 31)
#age = calculate_age(dob)
Cafe Gato Objects
Below is an example of using objects for my portion of our group project (linked here). As shown on that page, my use of CRUD mainly involves letting a user create a personal event at the cafe, with details clearly listed in a readable table.
To go along with that, below, I've created the object Event
, which includes all attributes that are also listed on the frontend version.
Attributes, Getters and Setters
class Event:
def __init__(self, name, email, event_name, event_details, date, start_time, end_time):
self._name = name
self._email = email
self._event_name = event_name
self._event_details = event_details
self._date = date
self._start_time = start_time
self._end_time = end_time
#here's the name getter
@property
def name(self):
return self._name
#here's the name setter
@name.setter
def name(self, name):
self._name = name
#here's the email getter
@property
def email(self):
return self._email
#here's the email setter
@email.setter
def email(self, email):
self._email = email
#here's the event_name getter
@property
def event_name(self):
return self._event_name
#here's the event_name setter
@event_name.setter
def event_name(self, event_name):
self._event_name = event_name
#here's the event_details getter
@property
def event_details(self):
return self._event_details
#here's the event_details setter
@event_details.setter
def event_details(self, event_details):
self._event_details = event_details
#here's the date getter
@property
def date(self):
return self._date
#here's the date setter
@date.setter
def date(self, date):
self._date = date
#here's the start_time getter
@property
def start_time(self):
return self._start_time
#here's the start_time setter
@start_time.setter
def start_time(self, start_time):
self._start_time = start_time
#here's the end_time getter
@property
def end_time(self):
return self._end_time
#here's the end_time setter
@end_time.setter
def end_time(self, end_time):
self._end_time = end_time
Tests
Here are two tests that are applicable with our site.
(The date
attribute is formatted as a string in the "mm/dd/yyyy"
format and the start_time
and end_time
attributes are both formatted as "hh/mm"
, with hours in military time. This is due to how the <input type="date">
and <input type="time">
tags format their values. With that in mind, the tests are...)
- A test that lists the dates of the events and identifies the earliest.
- A test that lists the start and end time of each event (in AM/PM format) and identifies whether or not the event occurs at a valid time for the day of the week it takes place in.
from datetime import *
if __name__ == "__main__":
#defining the three events for testing
e1 = Event(name="Thomas Edison", email="tedison@lightbulb.edu",
event_name="The Edison Troupe Meet",
event_details="We 10 selected geniuses will meet in the events room for a convergence.",
date="02/23/2023", start_time="13:00", end_time="14:00")
e2 = Event(name="John Mortensen", email="jmortensen@powayusd.com",
event_name="Extra Credit Code Meetup",
event_details="Come to work on ideation and any confusion with the Full Stack CPT project. No phones.",
date="02/25/2023", start_time="09:00", end_time="11:00")
e3 = Event(name="Karl Giant", email="giantrichguy@wallstreet.org",
event_name="Karl and Cats",
event_details="Karl would like to see cats with friends (if he can fit in the building).",
date="02/26/2023", start_time="16:00", end_time="17:00")
events = [e1, e2, e3]
# START OF TEST 1
print("TEST 1 BELOW:")
datelist = []
for event in events:
datelist.append(date(int(event._date[6:10]), int(event._date[0:2]), int(event._date[3:5])))
soonest = datelist[2]
for index, date in enumerate(datelist):
if date <= soonest:
soonest = date
soonind = index
for index, event in enumerate(events):
if index == soonind:
print("* ", end="")
print(event._event_name + ":", event._date)
# START OF TEST 2
print("\nTEST 2 BELOW:")
startlist = []
endlist = []
for event in events:
if 0 < int(event._start_time[0:2]) < 12:
startlist.append(str(int(event._start_time[0:2])) + ":" + event._start_time[3:5] + " AM")
elif int(event._start_time[0:2]) > 12:
startlist.append(str(int(event._start_time[0:2]) - 12) + event._start_time[2:5] + " PM")
elif int(event._start_time[0:2]) == 12:
startlist.append("12:" + event._start_time[3:5] + " PM")
else:
startlist.append("12:" + event._start_time[3:5] + " AM")
if 0 < int(event._end_time[0:2]) < 12:
endlist.append(str(int(event._end_time[0:2])) + ":" + event._end_time[3:5] + " AM")
elif int(event._end_time[0:2]) > 12:
endlist.append(str(int(event._end_time[0:2]) - 12) + event._end_time[2:5] + " PM")
elif int(event._start_time[0:2]) == 12:
endlist.append("12:" + event._end_time[3:5] + " PM")
else:
endlist.append("12:" + event._end_time[3:5] + " AM")
for index, event in enumerate(events):
if datetime.weekday(datelist[index]) < 5:
if (8 <= int(event._start_time[0:2]) < 17) and (8 < int(event._end_time[0:2]) <= 17):
print("Valid: ", end="")
else:
print("Invalid: ", end="")
else:
if (10 <= int(event._start_time[0:2]) < 18) and (10 < int(event._end_time[0:2]) <= 18):
print("Valid: ", end="")
else:
print("Invalid: ", end="")
print(event._event_name, "(" + startlist[index], "to", endlist[index] + ")")
(The "Extra Credit Code Meetup" was invalid because it was scheduled for 9:00 AM on a Saturday. According to the cafe hours, they open at 10:00 AM on Saturdays, meaning the event is scheduled for before opening. This makes it invalid.)