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
gaetano amoroso
2,993 PointsYet isn't clear one thing again in quiz.py second part! below, I post my code, help me please again
This is the questions.py
class Question:
answer = None
text = None
class Add(Question):
def __init__(self, num1, num2):
self.text = '{} + {}'.format(num1, num2)
self.answer = num1 + num2
class Multiply(Question):
def __init__(self, num1, num2):
self.text = '{} x {}'.format(num1, num2)
self.answer = num1 * num2
** Instead here thre is a file quiz.py**
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)
question = random.choice(question_types)(num1, num2)
# add these questions into self.questions
self.questions.append(question)
def take_quiz(self):
# log the start time
self.start_time = datetime.datetime.now()
# ask all of the questions
for question in self.questions:
# log if they got the question right
self.answers.append(self.ask(question))
else:
# log the end time
self.end_time = datetime.datetime.now()
# show a summary
return self.summary()
def ask(self, question):
correct = False
# log the start time
question_start = datetime.datetime.now()
# capture the answer
answer = input(question.text + ' = ')
# check the answer
if answer == str(question.answer):
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 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()
Hence, is more correct if I say that self refers to the attributes of an instance of the class itself, but in the code above if I want get the attributes start_time and end_time go back me message that says: AttributeError: 'Quiz' object has no attribute 'start_time'.
The same thing happen though I refer them after that (take_quiz()) it has been run . Still ,because ** summary() sees them**?
2 Answers
Chris Freeman
Treehouse Moderator 68,468 PointsAll of the methods, such as take_quiz(), ask(), summary(), etc. are all passed a reference to the current instance through the self parameter.
Printing the "directory" of self would show all of the attributes of the current instance. By inserting the line:
print(dir(self))
just before the return statement of take_quiz, it prints out the following:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'answers', 'ask', 'end_time', 'questions', 'start_time', 'summary', 'take_quiz', 'total_correct']
This shows all of the objects (methods and attributes) of the Quiz() instance. This can be thought of as the namespace of the instance. Here, you can see the 'end_time and start_time attributes added by the take_quiz() method. All methods have access to this namespace through the self reference. This is why the self.summary() reference works within the take_quiz method and why the self.start_time reference works within the summary method. It all goes through the namespace
To see a list of the attributes of self, add the print(self.__dict__) this will show the attributes and their values:
{'end_time': datetime.datetime(2016, 4, 15, 3, 17, 36, 992210), 'start_time': datetime.datetime(2016, 4, 15, 3, 17, 33, 315770)}
Don't worry about the __var__ methods. Those are inherited from the base class object.
This is getting to more advanced aspects of Python. It worth coming back to this discussion after you've progressed further in the language. It all will make sense soon enough.
gaetano amoroso
2,993 Pointsvery good
gaetano amoroso
2,993 PointsYet isn't clear one thing again in quiz.py second part! below, I post my code, help me please again
Of course , it works fine why is the code of Kenneth Love teacher but I'm not sure about how the variables work (start time) and (end _time). I don't understand hpw them work. why summary() method can print them, how can see them also if them stay within a function and moreover they haven't been give to summary() as argument
Chris Freeman
Treehouse Moderator 68,468 PointsChris Freeman
Treehouse Moderator 68,468 PointsNot sure what the question is. Your code works for me as is. Under what conditions are you seeing the AttributeError?