Class and Object Terms

The foundations of Object-Oriented Programming is defining a Class

  • In Object-Oriented Programming (OOP), a class is a blueprint for creating an Object. (a data structure). An Object is used like many other Python variables.
  • A Class has ...
    • a collection of data, these are called Attributes and in Python are pre-fixed using the keyword self
    • a collection of Functions/Procedures. These are called *Methods when they exist inside a Class definition.
  • An Object is created from the Class/Template. Characteristics of objects ...
    • 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())
  • A Python Class allow for the definition of @ decorators, these allow access to instance data without the use of functions ...
    • @property decorator (aka getter). This enables developers to reference/get instance data in a shorthand fashion (object.name versus object.get_name())
    • @name.setter decorator (aka setter). This enables developers to update/set instance data in a shorthand fashion (object.name = "John" versus object.set_name("John"))
    • observe all instance data (self._name, self.email ...) are prefixed with "", this convention allows setters and getters to work with more natural variable name (name, email ...)

Class and Object Code

# Werkzeug is a collection of libraries that can be used to create a WSGI (Web Server Gateway Interface)
# 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
from datetime import date 

# 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, gradClass, dob, age): # name, uid, and password are presets for each user
        self._name = name    # variables with self prefix become part of the object, 
        self._uid = uid
        self.set_password(password)
        self._dob = dob
        self._age = age
        self._gradClass = gradClass

    # 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
    
    @property 
    def gradClass(self):
        return self._gradClass

    @gradClass.setter
    def gradClass(self, gradClass):
        self._gradClass = gradClass

    
    # 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}", gradClass: "{self.gradClass}", dob: "{self.dob}", age: "{self.age}"'

    # output command to recreate the object, uses attribute directly
    def __repr__(self):
        return f'Person(name={self._name}, uid={self._uid}, password={self._password}, gradClass={self._gradClass}, dob={self.dob}, age={self._age})' # return will store the name back to you but not print it

 # a name getter method, extracts date of birth from object
    @property
    def dob(self):
        return self._dob
    
    # a setter function, allows date of birth to be updated after initial object creation
    @dob.setter
    def dob(self, dob):
        self._dob = dob

    @property 
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age

# tester method to print users
def tester(users, uid, psw, gradClass, dob, age):
    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

from datetime import date

def calculate_age(born):
    today = date.today()
    return today.year - born.year - ((today.month, today.day) < (born.month, born.day)) 


# place tester code inside of special if!  This allows include without tester running
if __name__ == "__main__": # to see the actual code, it is important bc everything under here is only rn in the file it is in

    # define user objects
    u1 = User(name='Joselyn Anda', uid='jesa06', password='123ellyna', gradClass=2024, dob=[2006, 1, 15], age= calculate_age(date(2006, 1, 15)))
    u2 = User(name='Naja Fonseca', uid='NajaAFonseca', password='123gibson', gradClass=2025, dob=[2007, 9, 20], age= calculate_age(date(2007, 9, 20)))
    u3 = User(name='Sean Yeung', uid='syeung', password='123taylor', gradClass=2013, dob=[1995, 2, 3], age= calculate_age(date(1995, 2, 3)))
    u4 = User(name='Amitha Sanka', uid='amitha-s', password='123coco', gradClass=2023, dob=[2005, 10, 31], age= calculate_age(date(2005, 10, 1)))

    # put user objects in list for convenience
    users = [u1, u2, u3, u4]

    # print(u1.name + " is " + calculate_age(u1.dob) + " years old")
    # Find user

    print("Test 1, find user 3")
    u = tester(users, u3.uid, "123taylor", u3.gradClass, u3.dob, u3.age )

    
    # Change user
    print("Test 2, change user 3 from Mr.Yeung to Lina")
    u.name = "Lina Awad"
    u.uid = "linaawad7"
    u.set_password("123thomas")
    u.gradClass = 2024
    u.dob = [2005, 10, 28]
    u.age = calculate_age(date(2005, 10, 28))
    u = tester(users, u.uid, "123thomas", u.gradClass, u.dob, u.age)


    # 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)
Test 1, find user 3
name: "Joselyn Anda", id: "jesa06", psw: "sha256$hDC...", gradClass: "2024", dob: "[2006, 1, 15]", age: "17"
name: "Naja Fonseca", id: "NajaAFonseca", psw: "sha256$B9U...", gradClass: "2025", dob: "[2007, 9, 20]", age: "15"
* name: "Sean Yeung", id: "syeung", psw: "sha256$inu...", gradClass: "2013", dob: "[1995, 2, 3]", age: "27"
name: "Amitha Sanka", id: "amitha-s", psw: "sha256$u0B...", gradClass: "2023", dob: "[2005, 10, 31]", age: "17"
Test 2, change user 3 from Mr.Yeung to Lina
name: "Joselyn Anda", id: "jesa06", psw: "sha256$hDC...", gradClass: "2024", dob: "[2006, 1, 15]", age: "17"
name: "Naja Fonseca", id: "NajaAFonseca", psw: "sha256$B9U...", gradClass: "2025", dob: "[2007, 9, 20]", age: "15"
* name: "Lina Awad", id: "linaawad7", psw: "sha256$Guk...", gradClass: "2024", dob: "[2005, 10, 28]", age: "17"
name: "Amitha Sanka", id: "amitha-s", psw: "sha256$u0B...", gradClass: "2023", dob: "[2005, 10, 31]", age: "17"
Test 3, make a dictionary
[{"_name": "Joselyn Anda", "_uid": "jesa06", "_password": "sha256$hDC0Uu1eBfUgH5CG$14972633112ad3e1e005480e9b13bab3eaf366c68126ba4f712aa9143dd875e5", "_dob": [2006, 1, 15], "_age": 17, "_gradClass": 2024}, {"_name": "Naja Fonseca", "_uid": "NajaAFonseca", "_password": "sha256$B9U6zH0LiHOSQNzj$4bb62f8625a6a1282a7d387110807421b4c690768c0f9c2f4e3ea9d47bccc831", "_dob": [2007, 9, 20], "_age": 15, "_gradClass": 2025}, {"_name": "Lina Awad", "_uid": "linaawad7", "_password": "sha256$Gukz7hc5NwKcEvh3$c8ec60f3c8f49a3159d98deb509a8e774cfc22fb4189d4d14f430188236d7518", "_dob": [2005, 10, 28], "_age": 17, "_gradClass": 2024}, {"_name": "Amitha Sanka", "_uid": "amitha-s", "_password": "sha256$u0BWTXdlEnNmqGv0$49b76c495ef0d8d729e2d84a589bda69a1c54ac34129218910f05de918b87882", "_dob": [2005, 10, 31], "_age": 17, "_gradClass": 2023}]
Test 4, make a dictionary
[{"_name": "Joselyn Anda", "_uid": "jesa06", "_password": "sha256$hDC0Uu1eBfUgH5CG$14972633112ad3e1e005480e9b13bab3eaf366c68126ba4f712aa9143dd875e5", "_dob": [2006, 1, 15], "_age": 17, "_gradClass": 2024}, {"_name": "Naja Fonseca", "_uid": "NajaAFonseca", "_password": "sha256$B9U6zH0LiHOSQNzj$4bb62f8625a6a1282a7d387110807421b4c690768c0f9c2f4e3ea9d47bccc831", "_dob": [2007, 9, 20], "_age": 15, "_gradClass": 2025}, {"_name": "Lina Awad", "_uid": "linaawad7", "_password": "sha256$Gukz7hc5NwKcEvh3$c8ec60f3c8f49a3159d98deb509a8e774cfc22fb4189d4d14f430188236d7518", "_dob": [2005, 10, 28], "_age": 17, "_gradClass": 2024}, {"_name": "Amitha Sanka", "_uid": "amitha-s", "_password": "sha256$u0BWTXdlEnNmqGv0$49b76c495ef0d8d729e2d84a589bda69a1c54ac34129218910f05de918b87882", "_dob": [2005, 10, 31], "_age": 17, "_gradClass": 2023}]

Hacks

Add new attributes/variables to the Class. Make class specific to your CPT work.

  • Add classOf attribute to define year of graduation
    • Add setter and getter for classOf
  • Add dob attribute to define date of birth
    • This will require investigation into Python datetime objects as shown in example code below
    • Add setter and getter for dob
  • Add instance variable for age, make sure if dob changes age changes
    • Add getter and setter for age
  • Update and format tester function to work with changes

Start a class design for each of your own Full Stack CPT sections of your project

  • Define init and self attributes
  • Define setters and getters
  • Make a tester

Start Code for Hacks

from datetime import date

def calculate_age(born):
    today = date.today()
    return today.year - born.year - ((today.month, today.day) < (born.month, born.day))

dob = date(1975, 12, 9)
age = calculate_age(date(1975, 12, 9))
print(age)
47

Vocabulary

  1. init- method that lets the class initialize the object's attributes. The init command initializes and controls processes. Its primary role is to start processes based on records read from the /etc/inittab file. The /etc/inittab file usually requests that the init command run the getty command for each line on which a user can log in.
  2. self attributes- allows setters and getters to work with more natural variable names, self. helps us access the attributes and methods of the class in python. It binds the attributes with the given arguments.
  3. setters- lets us update/set instance data in a shorthand fashion
  4. getters- lets us reference/get instance data in a shorthand fashion