Python - Classes and OOP Basics

Go To


I do not fully understand classes. I have read the python documentation and several other tutorials. I get the basic gist of it but don't understand the nuance. For instance in my code here:

class whiteroom():
    """ Pick a door: red, blue, green, or black. """

    do = raw_input("> ")

    if "red" in do:
        print "You entered the red room."

    elif "blue" in do:
        print "You entered the blue room."

    elif "green" in do:
        print "You entered the green room."

    elif "black" in do:
        print "You entered the black room."

        print "You sit patiently but slowly begin to stave.  You're running out of time."
        return whiteroom()

game = whiteroom()

(original codepad)

I would like to return the class whiteroom. Which is, either not possible, or not being done correctly. If you could clear up how to return a class or how to "link" two classes together so that whiteroom repeats on the else and the other rooms (which would be classes) are returned when called that would be awesome.

Also I'm super shaky on __init__ and am still not really sure what its purpose is. Everyone keeps telling me that it "initializes", which I'm sure it does, but that doesn't seem to be helping my brain out.

2012-04-04 04:16
by Colton Allen


Functions are very different from classes. It looks like you took a function and just changed the def to class. I guess that mostly works in your case, but it's not how classes are supposed to go.

Classes contain functions (methods) and data. For example, you have a ball:

class Ball(object):
    # __init__ is a special method called whenever you try to make
    # an instance of a class. As you heard, it initializes the object.
    # Here, we'll initialize some of the data.
    def __init__(self):
        # Let's add some data to the [instance of the] class.
        self.position = (100, 100)
        self.velocity = (0, 0)

    # We can also add our own functions. When our ball bounces,
    # its vertical velocity will be negated. (no gravity here!)
    def bounce(self):
        self.velocity = (self.velocity[0], -self.velocity[1])

Now we have a Ball class. How can we use it?

>>> ball1 = Ball()
>>> ball1
<Ball object at ...>

It doesn't look very useful. The data is where it could be useful:

>>> ball1.position
(100, 100)
>>> ball1.velocity
(0, 0)
>>> ball1.position = (200, 100)
>>> ball1.position
(200, 100)

Alright, cool, but what's the advantage over a global variable? If you have another Ball instance, it will remain independent:

>>> ball2 = Ball()
>>> ball2.velocity = (5, 10)
>>> ball2.position
(100, 100)
>>> ball2.velocity
(5, 10)

And ball1 remains independent:

>>> ball1.velocity
(0, 0)

Now what about that bounce method (function in a class) we defined?

>>> ball2.bounce()
>>> ball2.velocity
(5, -10)

The bounce method caused it to modify the velocity data of itself. Again, ball1 was not touched:

>>> ball1.velocity


A ball is neat and all, but most people aren't simulating that. You're making a game. Let's think of what kinds of things we have:

  • A room is the most obvious thing we could have.

So let's make a room. Rooms have names, so we'll have some data to store that:

class Room(object):
    # Note that we're taking an argument besides self, here.
    def __init__(self, name): = name  # Set the room's name to the name we got.

And let's make an instance of it:

>>> white_room = Room("White Room")
'White Room'

Spiffy. This turns out not to be all that useful if you want different rooms to have different functionality, though, so let's make a subclass. A subclass inherits all functionality from its superclass, but you can add more functionality or override the superclass's functionality.

Let's think about what we want to do with rooms:

We want to interact with rooms.

And how do we do that?

The user types in a line of text that gets responded to.

How it's responded do depends on the room, so let's make the room handle that with a method called interact:

class WhiteRoom(Room):  # A white room is a kind of room.
    def __init__(self):
        # All white rooms have names of 'White Room'. = 'White Room'

    def interact(self, line):
        if 'test' in line:
            print "'Test' to you, too!"

Now let's try interacting with it:

>>> white_room = WhiteRoom()  # WhiteRoom's __init__ doesn't take an argument (even though its superclass's __init__ does; we overrode the superclass's __init__)
>>> white_room.interact('test')
'Test' to you, too!

Your original example featured moving between rooms. Let's use a global variable called current_room to track which room we're in.1 Let's also make a red room.

1. There's better options besides global variables here, but I'm going to use one for simplicity.

class RedRoom(Room):  # A red room is also a kind of room.
    def __init__(self): = 'Red Room'

    def interact(self, line):
        global current_room, white_room
        if 'white' in line:
            # We could create a new WhiteRoom, but then it
            # would lose its data (if it had any) after moving
            # out of it and into it again.
            current_room = white_room

Now let's try that:

>>> red_room = RedRoom()
>>> current_room = red_room
'Red Room'
>>> current_room.interact('go to white room')
'White Room'

Exercise for the reader: Add code to WhiteRoom's interact that allows you to go back to the red room.

Now that we have everything working, let's put it all together. With our new name data on all rooms, we can also show the current room in the prompt!

def play_game():
    global current_room
    while True:
        line = raw_input( + '> ')

You might also want to make a function to reset the game:

def reset_game():
    global current_room, white_room, red_room
    white_room = WhiteRoom()
    red_room = RedRoom()
    current_room = white_room

Put all of the class definitions and these functions into a file and you can play it at the prompt like this (assuming they're in

>>> import mygame
>>> mygame.reset_game()
>>> mygame.play_game()
White Room> test
'Test' to you, too!
White Room> go to red room
Red Room> go to white room
White Room>

To be able to play the game just by running the Python script, you can add this at the bottom:

def main():

if __name__ == '__main__':  # If we're running as a script...

And that's a basic introduction to classes and how to apply it to your situation.

2012-04-04 04:58
by icktoofay
That Ball shouldn't be a class. Rule of thumb: If it has only two methods, one of which is __init__, you should use a function and functools.partial to bind the function to some data. Same for the other classes presented here. Python is not Java! The only thing I see here that should be a class is the game itself, for which you use module-global state instead - Niklas B. 2012-04-04 14:55
In the user exercise portion I tried to make it possible to go from white room to red room. But I cannot. I added "if "x" in line: currentroom = redroom" The current room variable does not change. However if I do something like: "if "x" in line: print "this"" it works. Thank you for your post. It was super helpful - Colton Allen 2012-04-04 20:14
Nevermind I figured it out! Thanks again for your help : - Colton Allen 2012-04-04 20:21
@Niklas: Yes; the game state really should be in a class; I was trying to make it as simple as possible, however, and I felt that making the game state a class might make my answer more confusing. Secondly, perhaps some of these things should not have been classes, but given that I was trying to demonstrate how to use classes, I think it was reasonable to use them. Besides, I think someone could think of other methods and data to add to the classes - icktoofay 2012-04-05 04:11
@icktoofay: Yep, I think you have a point :) +1 for a long and very detailed explanation - Niklas B. 2012-04-05 04:13


I'm sure you've heard all this before, but I'll give it a go.

Classes are a way to group up a bunch of function and variables into a single object. When you get all the way down to it, this is simply a way of organizing everything into groups that make sense. There are benefits down the road for making things easier to understand, debug, extend, or maintain, but basically its just a way to make something more defined in your mental model.

Your code looks like you are trying to write your entire program inside an 'object' (really, you just have an incorrectly written function).

Consider this instead.

Think of your mental model of rooms which have doors to them and whiteboards in them. Doors have a color. Also, whiteboards can have some text written on them. We'll leave it there to be simple.

To me, this suggests 3 different objects -- a door object that has a string for color, a whiteboard object that has a string for the text, and a room object that has a door and a whiteboard.

Consider the following code:

class Door(object):
    def __init__(self, color):
        self.color = color

class Whiteboard(object):
    def __init__(self, default_text=''):
        self.text = ''

    def write_text(self, text):
        self.text += text

    def erase(self):
        self.text = ''

class Room(object):
    def __init__(self, doorcolor, whiteboardtext=''):
        self.whiteboard = Whiteboard(whiteboardtext)
        self.door = Door(doorcolor)

# make a room with a red door and no text on the whiteboard
room1 = Room('red')

# make a room with a blue door and 'yeah, whiteboard' on the whiteboard
room2 = Room('blue', 'yeah, whiteboard')

# make a room with a green door
room3 = Room('green')

# now I can play around with my 'rooms' and they keep track of everything internally

print 'room 1 door color: ' + room1.door.color
print 'room 2 door color: ' + room2.door.color

# all my rooms have a door and a whiteboard, but each one is different and self contained. For example
# if I write on room 1's whiteboard, it doesn't change anything about room 3s

print 'room1 whiteboard: ' + room1.whiteboard.text
print 'room2 whiteboard: ' + room2.whiteboard.text
print 'room3 whiteboard: ' + room3.whiteboard.text

print '-- changeing room 1 whiteboard text --'

room1.whiteboard.write_text('oop is really helpful')

print 'room1 whiteboard: ' + room1.whiteboard.text
print 'room2 whiteboard: ' + room2.whiteboard.text
print 'room3 whiteboard: ' + room3.whiteboard.text

The init function is what gets called when you 'initialize' a new instance of your class. In the example I am making 3 Room objects which each create a Door and Whiteboard object internally. The parameters I pass into the constructor Room(parameter1, parameter2) get passed to the init functions - you can see I'm using this to set the door color and optionally some text on the whiteboard. Also notice that the variables that 'belong' to the objects are referenced with self - this reference is what gets passed in as the first parameter to all class functions (and becomes more important later when you are extending classes and other more advanced things).

2012-04-04 04:36
by Collin Green


Well I understood OOPS in Python from Learning Python by Mark Lutz. It is a comprehensive source for understanding Python concepts especially to code the Pythonic way.

For your online reference, I like the tutorials from this site. Go through this post, it will help you with init. OOPs in Python is very easy to understand and implement. It seems daunting at first but its a breeze after you program some basic OOP codes. Enjoy learning..

2012-04-04 04:44
by Mellkor


You're really far off.

Sorry to say it, but this is just barely salvageable.

From what I can tell you want something like a room class, for instance:

class Room(object):
    ''' A generic room '''
    def __init__(self):
        self.choices = None
    def enter(self):
        ''' Enter the room, to be filled out in subclass '''
    def print_choices(self):
        '''You are stuck bro'''
        print "You are stuck bro"

Then you can make a specific room like the whiteroom like so:

class Whiteroom(Room):
    ''' A white room '''
    def __init__(self):
        self.choices = ["red", "blue", "green", "black"]
    def enter(self):
        print "You sit patiently, but slowly begin to starve.  You're running out of time."
    def print_choices(self):
        print "You can choose from the following rooms:"
        print self.choices

class Blackroom(Room):
    ''' A black room '''
    def enter(self):
        print "It's really dark in here.  You're out of time."

class Redroom(Room):
    ''' A red room '''
    def __init__(self):
        self.choices = ["black", "blue", "green", "white"]
    def enter(self):
        print "It's getting hot in here.  So take off all your clothes."
    def print_choices(self):
        print "You can choose from the following rooms:"
        print self.choices

class Blueroom(Room):
    ''' A blue room '''
    def __init__(self):
        self.choices = ["black", "red", "green", "white"]
    def enter(self):
        print "It's nice and cool in here.  Stay awhile if you want."
    def print_choices(self):
        print "You can choose from the following rooms:"
        print self.choices

class Greenroom(Room):
    ''' A green room '''
    def __init__(self):
        self.choices = ["black", "red", "blue", "white"]
    def enter(self):
        print "You won."

Then you'd have do this to run the game:

print "Type 'quit' to quit"
print "Type 'choices' to see what your choices are"

current_room = Whiteroom()
done = False
while (not done):
    entry = raw_input("> ")
    if entry == "quit":
        done = True
    if "choices" in entry:
    if current_room.choices:
        if entry in current_room.choices:    
            if "white" in entry:
                current_room = Whiteroom()

            if "black" in entry:
                current_room = Blackroom()

            if "red" in entry:
                current_room = Redroom()

            if "green" in entry:
                current_room = Greenroom()
                done = True

            if "blue" in entry:
                current_room = Blueroom()

That's my best attempt at turning your snippet into an actual game, using classes.

2012-04-04 05:10
by jgritty


Object Oriented Programming can be a very fun thing to grasp at first, the only way to really hash through it is to actually take the time to do a lot of reading, and practice. A good place to begin would be here. and

2012-04-04 04:22
by JDD