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

from werkzeug.security import generate_password_hash, check_password_hash
import json
from datetime import date, datetime
from dateutil.relativedelta import relativedelta
def calculate_age(born):
    today = date.today()
    return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
def jsonSerial(obj):
    """JSON serializer for objects not serializable by default json code"""

    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    raise TypeError ("Type %s not serializable" % type(obj))
class User:    

    def __init__(self, name, uid, password, ClassOf, dob):
        self._name = name     
        self._uid = uid
        self._ClassOf = ClassOf
        self.dob = dob
        self.set_password(password)

    @property
    def name(self):
        return self._name
    
    @name.setter
    def name(self, name):
        self._name = name
    @property
    def age(self):
        today = date.today()
        return today.year - self._dob.year - ((today.month, today.day) < (self._dob.month, self._dob.day))

    @property
    def dictionary(self):
        dict = {
            "name" : self.name,
            "uid" : self.uid,
            "dob" : self.dob,
            "age" : self.age
        }
        return dict
    
    @property
    def ClassOf(self):
        return self._ClassOf
    
    @ClassOf.setter
    def ClassOf(self, ClassOf):
        self._ClassOf = ClassOf
    
    @property
    def dob(self):
        return self._dob
    
    @dob.setter
    def dob(self, dob):
        self._dob = dob

    @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] + "..." 
    def __str__(self):
        return json.dumps(self.dictionary)
  
    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 __repr__(self):
        return f'User(name={self._name}, uid={self._uid}, password={self._password},dob={self._dob})'
    

    def __str__(self):
        return json.dumps(self.dictionary)

    def ToJSON(self):
        ret =  {
            'name': self.name,
            'age': calculate_age(self.dob),
            'uid': self.uid,
            'classOf': self.ClassOf
        }
        return json.dumps(ret, default = jsonSerial)


    def __repr__(self):
        return f'User(name={self._name}, uid={self._uid}, password={self._password},dob={self._dob})'
    
    def tester(users, uid, psw):
        result = None
        for user in users:
        
            if user.uid == uid and user.is_password(psw): 
                print("* ", end="")
                result = user
        
            print(str(user))
        return result

    def __str__(self):
            return json.dumps(self.dictionary, default = jsonSerial )

if __name__ == "__main__":
    
    
    # define user objects
    u1 = User(name='Safin', uid='bobby', password='bobby11',dob = date(2006, 2, 11), ClassOf = 2024)
    u2 = User(name='Kaiden', uid='billy', password='123bill',dob = date(2005, 7, 10), ClassOf = 2024)
    u3 = User(name='Amay', uid='may', password='123may',dob = date(2006, 3, 3), ClassOf = 2024)
    u4 = User(name='Bron', uid='bronny', password='123bronnn',dob = date(1989, 12, 8), ClassOf = 2000)
    u5 = User(name='David', uid='vid', password='123vidd',dob = date(2006, 11, 9), ClassOf = 2024)


users = [u1, u2, u3, u4, u5]
for i in users:
    
    print("Here is info about", i.name + ",\n\t" ,i)
    print("Here is a representation of the class instance of ", i.name,"\n\t" +   repr(i))
    print("Here is a non-json description", "name:", i.name, "age:", i.age, "\n\n")
Here is info about Safin,
	 {"name": "Safin", "uid": "bobby", "dob": "2006-02-11", "age": 16}
Here is a representation of the class instance of  Safin 
	User(name=Safin, uid=bobby, password=sha256$2pvob4zLDf1wuhyp$af8363b52f67f598b3aafd0ac75b399cfa0ac70fdbe909f56db1f00ffc0758c6,dob=2006-02-11)
Here is a non-json description name: Safin age: 16 


Here is info about Kaiden,
	 {"name": "Kaiden", "uid": "billy", "dob": "2005-07-10", "age": 17}
Here is a representation of the class instance of  Kaiden 
	User(name=Kaiden, uid=billy, password=sha256$RtxVdTx3P3xIhlPt$b56ad6f232b28c5cb10fd6ca469d0c219c7d08cc7e34119a36f25c765f03da29,dob=2005-07-10)
Here is a non-json description name: Kaiden age: 17 


Here is info about Amay,
	 {"name": "Amay", "uid": "may", "dob": "2006-03-03", "age": 16}
Here is a representation of the class instance of  Amay 
	User(name=Amay, uid=may, password=sha256$y2aI8rskHyuY7qSG$d828972304ae5e2c917fc3b2046cf0903139b5379bce79fe714ac433f194a5bb,dob=2006-03-03)
Here is a non-json description name: Amay age: 16 


Here is info about Bron,
	 {"name": "Bron", "uid": "bronny", "dob": "1989-12-08", "age": 33}
Here is a representation of the class instance of  Bron 
	User(name=Bron, uid=bronny, password=sha256$ma5jJtoeRRKYhFVg$2d97145750ed26c5c4e122d67ea98dfc607eb07c3172beb4e1ca1171a716ecc2,dob=1989-12-08)
Here is a non-json description name: Bron age: 33 


Here is info about David,
	 {"name": "David", "uid": "vid", "dob": "2006-11-09", "age": 16}
Here is a representation of the class instance of  David 
	User(name=David, uid=vid, password=sha256$BfsuMCoaq8hDjPGG$0b19798d8452e6f23dc277b78c787f8bc5623e1763ccfc76c9e29bd8d9f46037,dob=2006-11-09)
Here is a non-json description name: David age: 16 


import json

class task:
    def __init__(self, activity, time):
        self._time = time
        self._activity = activity

    @property
    def activity(self):
        return self._activity
    
    @activity.setter
    def task(self, activity):
        self._activity = activity

    @property
    def time(self):
        return self._time

    @time.setter
    def time(self, time):
        self._time = time
    
    @property
    def dict(self):
        data = {
            "Activity" : self.activity,
            "time" :self.time
        }
    
    def __str__(self):
        return json.dumps(self.dict)
    
    def __repr__(self):
        return f'user(Task={self._activity}, time={self._time})' 

class1 = task("Calc", 20)
class2 = task("CSP", 50)


print("Person 1 activity :", class1.activity)
print("person 1 time:", class1.time, "\n")

print("Person 2 activity :", class2.activity)
print("person 2 time:", class2.time)

print(repr(class1))
print(repr(class2))
Person 1 activity : Calc
person 1 time: 20 

Person 2 activity : CSP
person 2 time: 50
user(Task=Calc, time=20)
user(Task=CSP, time=50)

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 for age, but don't add/allow 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

  • Use new code cell in this notebook
  • 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(2004, 12, 31)
age = calculate_age(dob)
print(age)