Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python Object-Oriented Python (retired) Objects Create a Class with a Method

Garrett Phipps
PLUS
Garrett Phipps
Courses Plus Student 2,808 Points

Python Class Methods: What am I missing here? All I get is "bummer try again".

All I need to do is make a class method to return a string formatted with a generic store hours message. I have no idea what I'm missing, and the only error message given on the code challenge is "Bummer! Try again!" Would someone please point me in the right direction?

method.py
class Store:
    open = 9
    close = 22
    time = "We're open from {open} to {close}."

    def hours(self):
        return self.time.format(open, close)

3 Answers

James J. McCombie
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
James J. McCombie
Python Web Development Techdegree Graduate 21,137 Points

open and close are class attributes shared by all instances of the class. When your create an instance of the class, that instance has those attributes, but they have to belong to something, that being the class instance. So you can do something like this in the python shell (assuming you have already defined the class):

>>> store = Store()
>>> store.open
9
>>> store.close
22

you can see to get the value that the variables open and close are assigned too, you have to access the property of the class by typing store.open/close. Therefore in the method 'hours', you are passing in 'self' as an argument; you are passing the instance of the class itself into the function defined in the class. The variable name 'open' and 'close' are not defined globally, they only have real 'existence' as properties of a class instance. If you were to type open and close into the python shell even after defining a the Store class, you would get an error (unless you had defined them as 'normal' variables at some point - not as part of a class.

*Just to break to check you understand something specific about the format() method - apologies if i am preaching to the converted. '{} - {} - {}'.format('a', 'b', 'c') will output 'a - b - c' right? but, '{2} - {0} - {1}'.format('a', 'b', 'c') will produce...'c - a - b'. The numbers inside the parentheses refer to the index position of the arguments passed in the format method, in the first example there are three placeholders and three arguments, so python places each one sequentially in to the placeholder to print the output, default behaviour, if you have three placeholders and provide only one argument for example, you get an IndexError, but if you wrote a zero into each of the placeholders and provided only one argument, you get an output with the argument printed in each placeholder. This is only a little piece of the functionality of format.

Since you are passing in the class instance into the class method - the function hours - hours as an argument 'self', you can make use of it, and have to to get the class instance properties open, and close. This is why it has to be:

'we are open from {0.open} to {0.close)'.format(self)

or

'we are open from {} to {}'.format(self.open, self.close)

in the first example we provide one argument, self - the class instance which you can think of as being store, from store = Store(), and the placeholders have 0.open, 0.close, to tell python to take the one argument 'self' for each placeholder and do .open, and .close respectively. Think of this as writing store.open, store.close, but in the definition of a class we have to be more general hence the use of 'self'. In the second we have two arguments, self.open, self.close, which python inserts sequentially into the placeholders.

Just remember that any methods, or class attributes, or instance attributes (you may have not covered this just yet, does init ring any bells?) only have meaning as properties of an instance of a class, hence the use of self - the property/method of the instance itself.

Hopefully, that has not made the waters even more murky?

Garrett Phipps
Garrett Phipps
Courses Plus Student 2,808 Points

There's what I was missing! Thank you, that helps dramatically. Without this answer, I would've run into a similar one later. I didn't realize I could use indices to format, and it was unclear to me how to use attributes in formatting inside a class method.

Garrett Phipps
Garrett Phipps
Courses Plus Student 2,808 Points

When I did that without zeros it didn't work; why does "We're open from {open} to {close}.".format(self) not work?

Garrett Phipps
Garrett Phipps
Courses Plus Student 2,808 Points

So I ran it through the shell in Workspaces (duh, should've done that earlier) and with or without the braced keywords in the string it returns this error (I used the same code as above in my question):

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/treehouse/workspace/classescc.py", line 7, in hours
return self.time.format(open, close)
NameError: name 'close' is not defined

Now I don't understand why 'close' is apparently not defining... Any ideas?