Tuesday, January 26, 2021

Python - Class (Day 17)

This is a 100 Days challenge to learn a new language (Python). 100 Days of Code - The Complete Python Pro Bootcamp 

I will post some notes to motivate myself to finish this challenge.


How to create a class



Class is a Blueprint.
It starts with 'class' keyword, followed with class name.

Ex:
# Define a class
class User:
    # pass statement
    pass


# Use class to create an object
user = User()



Naming Convention


PascalCase (HelloWorld)

It is used by Python Class name. Reference.

# Class
class MyClass:
    pass


snake_case (hellow_world)

It is used by Python function name and variable name. Reference

# Custom Functions
def my_function():
    print("this is my function")


# Variables
int_val = 1


camelCase (helloWorld)


Used it in Python only if needed (backwards compatibility).  Reference


What is pass statement



Under 'How to create a class' section, what will it happen if we remove pass statement?
# Define a class
class User:
    # pass statement
    # pass


# Use class to create an object
user = User()


Error: 
user_1 = User()
^ IndentationError: expected an indented block


In python, empty code is not allowed in loops, function, class, and if else condition. 

Therefore, you will get an error if you run previous example since interpreter think you forget to give them some indents.

The solution is to add pass statement. 'pass' statement is used as a placeholder for future code. 
Also, note that interpreter will ignore comments totally, but 'pass' is not ignored.


Constructor



We can setup attributes of object after creating. This way is error prone because we might have typo.

Ex (Without Constructor):

# Define a Class without Constructor
class User:
    pass

# Using Class to create an object
user = User()
# set object attribute 'id' to 001
user.id = "001"

# if we have a typo (change i to l) from the previous instruction
# then user.id will not be setup
# and it is hard to debug
# user.ld = "001"

print(f"user id: { user.id}")


Constructor is also called initializer.
The recommended way to use.

Ex:

# Define a Class
class User:
# Constructor
    def __init__(self, id):
        self.id = id

# Using Class to create an object
user = User(1)

print(f"user id: {user.id}")


Then we just need to pass parameters to Class when creating.


What is 'self' in constructor?



self represents the instance of the class.
By using the 'self' keyword we can access the attributes and methods of the class in python. 


Adding methods



Ex:
# Define a class
class User:
    # Constructor
# Init attributes
    def __init__(self, user_id, username):
        self.id = user_id
        self.username = username
        self.followers = 0
        self.following = 0

    # Methods
    def follow(self, user):
        user.followers += 1
        self.following += 1

# Create objects
user_1 = User("001", "Frank")
user_2 = User("002", "Jake")
user_3 = User("003", "Mary")
# Call methods
user_2.follow(user_1)
user_3.follow(user_1)

print(
    f"user 1: {user_1.id} - {user_1.username} -
{user_1.followers} - {user_1.following}"
)
print(
    f"user 2: {user_2.id} - {user_2.username} -
{user_2.followers} - {user_2.following}"
)
print(
    f"user 3: {user_3.id} - {user_3.username} -
{user_3.followers} - {user_3.following}"
)


Result:

user 1: 001 - Frank - 2 - 0
user 2: 002 - Jake - 0 - 1 user 3: 003 - Mary - 0 - 1




Challenge - Build a Quiz Project


Build a quiz project with OOP style.
* Question class:
    attributes
        text
        answer
* QuizBrain class
    attributes
        score
        question_number
        question_list
    methods
        still_has_questions
        next_question
        check_answer

Ex: 
data.py (Quiz Resource)
question_data = [
    {
        "category": "Entertainment: Video Games",
        "type": "boolean",
        "difficulty": "easy",
        "question": "Peter Molyneux was the founder of Bullfrog
Productions.",
        "correct_answer": "True",
        "incorrect_answers": ["False"],
    },
    {
        "category": "Vehicles",
        "type": "boolean",
        "difficulty": "hard",
        "question": "In 1993 Swedish car manufacturer Saab experimented
with replacing the steering wheel
with a joystick in a Saab 9000.",
        "correct_answer": "True",
        "incorrect_answers": ["False"],
    },
    {
        "category": "General Knowledge",
        "type": "boolean",
        "difficulty": "easy",
        "question": "French is an official language in Canada.",
        "correct_answer": "True",
        "incorrect_answers": ["False"],
    },
]


question_model.py
class Question:
    """Question"""

    def __init__(self, text, answer):
        self.text = text
        self.answer = answer


question_model.py
class QuizBrain:
    """QuizBrain"""

    # Constructor
    def __init__(self, question_list):
        self.question_list = question_list
        self.score = 0
        self.question_number = 0

    def still_has_questions(self):

        if self.question_number >= len(self.question_list):
            return False

        return True

    def next_question(self):

        # Increase question number
        self.question_number += 1

        # Use (question_number - 1) as array index
        question = self.question_list[self.question_number - 1]

        # Ask user input
        user_answer = input(
            f"Q.{self.question_number }: {question.text} (True/False): "
        )

        # Determine the answer
        self.check_answer(user_answer, question.answer)

    def check_answer(self, user_answer, correct_answer):

        if user_answer == correct_answer:
            print("Right!")
            self.score += 1
        else:
            print("Opps")

        print(f"The correct answer is {correct_answer}")
        print(f"The current score is:
{self.score}/{self.question_number}")


With OOP design, QuizBrain did not need to generate the quiz list. The quiz list is passed by caller (main.py). So it is reusable if the quiz resource are coming from different website with different format.

Caller (main.py) just need to format it and pass it when initializing QuizBrain. Then QuizBrain can be reused by different program. That is the beauty of OOP.

No comments:

Post a Comment