Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

more clear about SELF

HI everyone! I have a question about self argument. In making quiz script we make classes. I do not understand why sometimes self is needed to be used inside methods and sometimes not. For example:

def take_quiz(self):
    self.start_time = datetime.datetime.now()
    for question in self.questions:
      self.answers.append(self.ask(question)) 
    else:                       
      self.end_time = datetime.datetime.now()
    return self.summary()

 # Answers and questions are attributes of the class Quiz, 
# if I undestand right, this is why we need to put self before them. 

def ask(self, question):
    correct = False
    question_start = datetime.datetime.now()
    answer = input(question.text + ' = ')
    question_end = datetime.datetime.now()
    if answer == str(question.answer):
      correct = True
    return correct, question_end - question_start

But why self is not used with question_start and question_end, when it's used with start_time and end_time. And why self isn't used with correct variable or answer input?

1 Answer

Hi Iskander,

Self is used to describe the class instance that was created. So, anytime you refer to an attribute of that instance specifically, you'll want to refer to self. In the above example, start_time, questions, answers, end_time, and summary are all attributes of the class; referring to them with self lets Python know that you mean to refer to those variables in the instance which is utilizing the method take_quiz().

On the other hand, ask() doesn't refer to attributes of a class instance, so you don't need to tell it to refer to self - as long as your question being passed in is an object with text and answer attributes, it doesn't matter what state the instance of the class is for you to be able to use ask().

Hope that helps!

Thank you Evan, but I still do not understand - how can start_time and end_time be attributes of class Quiz, if they are not represented as the attributes (sorry, I should have shown whole code from the begining):

import datetime
import random

from questions import Add, Multiply


class Quiz:
    questions = []
    answers = []

    def __init__(self):
        question_types = (Add, Multiply)
        # generate 10 random questions with numbers from 1 to 10
        for _ in range(10):
            num1 = random.randint(1, 10)
            num2 = random.randint(1, 10)
            quest = random.choice(question_types)(num1, num2)
            # add these questions into self.questions
            self.questions.append(quest)

    def take_quiz(self):
        # log the start time
        self.start_time = datetime.datetime.now()

        # ask all of the questions
        for quest in self.questions:
            # log if they got the question right
            self.answers.append(self.ask(quest))
        else:
            # log the end time
            self.end_time = datetime.datetime.now()

        # show a summary
        return self.summary()


    def ask(self, quest):
        correct = False

        # log the start time
        question_start = datetime.datetime.now()

        # capture the answer
        answer = input(quest.text + ' = ')

        # check the answer
        if answer == str(quest.answer):
            self.correct = True

        # log the end time
        question_end = datetime.datetime.now()

        # if the answer's right, send back True
        # otherwise, send back False
        # send back the elapsed time, too
        return self.correct, question_end - question_start

    def total_correct(self):
        # return the total # of correct answers
        total = 0
        for answer in self.answers:
            if answer[0]:
                total += 1
        return total

    def summary(self):
        # print how many you got right and the total # of questions. 5/10
        print("You got {} out of {} right.".format(
                self.total_correct(), len(self.questions)
        ))
        # print the total time for the quiz: 30 seconds!
        print("It took you {} seconds total.".format(
                (self.end_time-self.start_time).seconds
        ))


Quiz().take_quiz()

They become attributes by way of using self; if you left self out and didn't declare the variables outside the method, then the variables you're assigning to self would only be usable within the scope of the method that declared them. Meaning that, in this case, summary() wouldn't be able to check self.start_time or self.end_time. Basically, self is directing Python to refer to the instance of the class.

As an example of in-scope variables, you can think of using multiple methods that all return a variable called result; outside those methods, there isn't a result variable floating around (unless you coded to have that specifically happen).

Now I get it, thank's a lot Evan)