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 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 ...)
# 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='Saavan Gade', 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)
Test 1, find user 3
name: "Saavan Gade", id: "toby", psw: "sha256$jR2..."
name: "Nicholas Tesla", id: "nick", psw: "sha256$n4T..."
* name: "Alexander Graham Bell", id: "lex", psw: "sha256$bFG..."
name: "Eli Whitney", id: "eli", psw: "sha256$Qas..."
name: "Hedy Lemarr", id: "hedy", psw: "sha256$hDy..."
Test 2, change user 3
name: "Saavan Gade", id: "toby", psw: "sha256$jR2..."
name: "Nicholas Tesla", id: "nick", psw: "sha256$n4T..."
* name: "John Mortensen", id: "jm1021", psw: "sha256$iCN..."
name: "Eli Whitney", id: "eli", psw: "sha256$Qas..."
name: "Hedy Lemarr", id: "hedy", psw: "sha256$hDy..."
Test 3, make a dictionary
[{"_name": "Saavan Gade", "_uid": "toby", "_password": "sha256$jR2LmCK0YUAHRCp4$d55f7acdc12a2061450bcf89758d6cfe42e60e20612174cfe58b2db8a6fc4e73"}, {"_name": "Nicholas Tesla", "_uid": "nick", "_password": "sha256$n4Tkv6qhHpfIARby$7952fbbf34ccce83d14caa113793e8aee43eec2dcc7968efb84c70b92c66e5bf"}, {"_name": "John Mortensen", "_uid": "jm1021", "_password": "sha256$iCNAwFvI9395z2Ja$733a2fc0439ec6e8fba85ec54b04b50c9bde3c2199b4f471884e7c752828de78"}, {"_name": "Eli Whitney", "_uid": "eli", "_password": "sha256$QasZkSusGOhxeErq$7330db1c7e514d9dd1e0d210161fc7f4ef5df7d582cefd1dce0e2f448faee9b2"}, {"_name": "Hedy Lemarr", "_uid": "hedy", "_password": "sha256$hDya3uIETozgImas$e77b7200ebd8dc3362b359c6ee39c97adce8f3ff3319e6ee890f16ed347b60b8"}]
Test 4, make a dictionary
[{"_name": "Saavan Gade", "_uid": "toby", "_password": "sha256$jR2LmCK0YUAHRCp4$d55f7acdc12a2061450bcf89758d6cfe42e60e20612174cfe58b2db8a6fc4e73"}, {"_name": "Nicholas Tesla", "_uid": "nick", "_password": "sha256$n4Tkv6qhHpfIARby$7952fbbf34ccce83d14caa113793e8aee43eec2dcc7968efb84c70b92c66e5bf"}, {"_name": "John Mortensen", "_uid": "jm1021", "_password": "sha256$iCNAwFvI9395z2Ja$733a2fc0439ec6e8fba85ec54b04b50c9bde3c2199b4f471884e7c752828de78"}, {"_name": "Eli Whitney", "_uid": "eli", "_password": "sha256$QasZkSusGOhxeErq$7330db1c7e514d9dd1e0d210161fc7f4ef5df7d582cefd1dce0e2f448faee9b2"}, {"_name": "Hedy Lemarr", "_uid": "hedy", "_password": "sha256$hDya3uIETozgImas$e77b7200ebd8dc3362b359c6ee39c97adce8f3ff3319e6ee890f16ed347b60b8"}]
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(2005, 7, 14)
age = calculate_age(dob)
print(age)
17
from datetime import date
import json

class Student:
    def __init__(self, name:str, dob:date, graduation_year:int):
        self.name = name
        self.dob = dob
        self.graduation_year = graduation_year
        self.age = self.calculate_age()

    def calculate_age(self) -> int:
        today = date.today()
        age = today.year - self.dob.year - ((today.month, today.day) < (self.dob.month, self.dob.day))
        self.age = age
        return age

    def get_dob(self) -> date:
        return self.dob
    
    def change_dob(self, new_dob:date) -> str:
        self.dob = new_dob
        self.age = self.calculate_age()
        return f"Date of Birth changed to {self.dob}"
    
    def get_age(self) -> int:
        return self.age
    
    def get_graduation_year(self) -> int:
        return self.graduation_year
    
    def change_graduation_year(self, new_graduation_year:int) -> str:
        self.graduation_year = new_graduation_year
        return f"Graduation year changed to {self.graduation_year}"
    
    def student_data(self) -> json:
        send_dob = self.dob.strftime("%m/%d/%Y")
        student_information = {
            "name": self.name,
            "dob": send_dob,
            "age": self.age,
            "graduation_year": self.graduation_year
        }
        return json.dumps(student_information)

    def __str__(self) -> str:
        return f"Name: {self.name}, Age: {self.age}, DOB: {self.dob}, Graduation year: {self.graduation_year}"

# Defining Student
Saavan = Student("Saavan", date(2005, 7, 14), 2023)

# Printing Json Data and Student Information
print(Saavan)
print(Saavan.student_data())

# Getting graduation year
print(f"\nSaavan is going to graduate in {Saavan.get_graduation_year()}")

# Setting graduation year
print(f"{Saavan.change_graduation_year(2028)}")
print(f"Saavan is now going to graduate in {Saavan.get_graduation_year()}\n")

# Getting DOB
print(f"Saavan was born on {Saavan.get_dob()}")
print(f"Saavan is {Saavan.get_age()} years old as of {date.today()}\n")

# Setting DOB
print(Saavan.change_dob(date(1950, 7, 14)))
print(f"Saavan is {Saavan.get_age()} years old as of {date.today()}\n")

# Printing Json Data and Student Information after updates
print(f"New Saavan is {Saavan}")
print(Saavan.student_data())
Name: Saavan, Age: 17, DOB: 2005-07-14, Graduation year: 2023
{"name": "Saavan", "dob": "07/14/2005", "age": 17, "graduation_year": 2023}

Saavan is going to graduate in 2023
Graduation year changed to 2028
Saavan is now going to graduate in 2028

Saavan was born on 2005-07-14
Saavan is 17 years old as of 2023-01-22

Date of Birth changed to 1950-07-14
Saavan is 72 years old as of 2023-01-22

New Saavan is Name: Saavan, Age: 72, DOB: 1950-07-14, Graduation year: 2028
{"name": "Saavan", "dob": "07/14/1950", "age": 72, "graduation_year": 2028}

Hack Relating to my Project

  • In this example, the class takes a password as input and uses it to check the strength of the password. It checks for the length of the password, if it has at least one uppercase letter, one lowercase letter, one digit, and one special character and assigns a score to the strength of the password.
  • Since my project is about keeping passwords safe I wanted to create a code where passwords were tested for their strenght as an additional feature.
class PasswordStrength:
    def __init__(self, password:str):
        self.password = password
        self.strength = 0
    
    def check_strength(self):
        if len(self.password) < 8:
            self.strength -= 1
        if not any(c.isupper() for c in self.password):
            self.strength -= 1
        if not any(c.islower() for c in self.password):
            self.strength -= 1
        if not any(c.isdigit() for c in self.password):
            self.strength -= 1
        if not any(c in "!@#$%^&*()_-+=[]{}|;':\"<>,.?/" for c in self.password):
            self.strength -= 1
        else:
            self.strength +=1
        return self.strength

password = input("Enter a password: ")
strength = PasswordStrength(password)
print(f"Password strength: {strength.check_strength()}")
Password strength: -4