An Object-Oriented Primer in Python: Part 2

In the first installment, we learned a bit about objects (they hold information, and do things), and how to use pre-built objects (object.method() for a method (aka function) and object.variable for a variable). Now let’s talk about making our own classes.

The class statement:

The way you make a class in Python is with…the class statement, the name of the class, and a colon. So our Dog class is:


class Dog:

Hard, isn’t it? :) And, in true Python style, everything that’s part of that class is indented. (But you already knew that, because of the colon, right? :) )

Methods

Methods are made in a very similar manner to standard functions. There’s two main differences: They require a parameter called “self”, and there’s a few reserved methods that do special things.

Our Dog class had a method called showBreed(). It looked like this:

    def showBreed(self):
        print "It's a %s"%self.breed

So we have the def statement, the name of the method, and then “self” is the only parameter. Self is kind of a tricky concept: It refers to the object that’s calling it. So when we print self.breed, we’re printing the string called breed from whatever happens to be calling it. If it helps, you can think of it as sort of a wildcard: It can be fido.breed, it can be spot.breed, it’s a placeholder to show that it’s somebody’s breed. If you don’t grok that, read it again: This was probably my biggest stumbling block when I learned it. Now that you have that cleared up, realize that you also need to put self in as the first parameter for every method you define, but that when you actually call, the method, you pretend it isn’t there. Maybe some error messages would help:

>>> class Error:
    def cry(self):
        print "Method called"

>>> e = Error()
>>> e.cry()
Method called
>>> e.cry(self)

Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    e.cry(self)
NameError: name 'self' is not defined
>>> class OtherError:
    def cry():
        print "Other method called"

>>> o = OtherError()
>>> o.cry()

Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    o.cry()
TypeError: cry() takes no arguments (1 given)

So, as you can see, calling a method with “self” raises one error, and defining a method with no “self” raises another one when it’s called–when you call it Python automatically includes the “self” (cry() takes no arguments  (1 given)).

__init__():

Now we come to one of the most important methods: __init__(): Observe:

>>> class Blog:
    def __init__(self, name):
        self.name = name

>>> RmI = Blog("Rannsaich mo Inntinn")
>>> RmI.name
'Rannsaich mo Inntinn'

__init__ (you can call it a constructor if you want) is called as soon as an object is initiated. Note how I never explicitly called it. The astute may have noticed that when I created the RmI object, it’s arguments matched __init__’s perfectly–the self is implicit, and the name is “Rannsaich mo Inntinn”. The very astute may have noticed that, actually, Blog was defined with no arguments in the beginning (you can have class Blog():, and put stuff in the parentheses, but that’s called inheritance and is a topic for another day).

You also see __init__ doing something it does a lot, doing self.xxxx = xxxx. This takes the xxxx (alright, in this case it’s name) parameter, and gives it a home as part of that object. Because if we didn’t do self.name = name, whatever value name was would get deleted as soon as __init__ was over, and there’d be no way of using it in other methods. Of course, you can use that elsewhere to, in Part 1 we manipulated self.breed directly, and you can also change self.xxxx from other methods. But __init__ is really the best for, um, initializing them.

Once you swallow all of that, go back to that Dog class, and see if you can write it. You know all of the components–try fitting them together. If you need help, post it in the comments.

—————

Here’s my Dog class, which you really shouldn’t be looking at, but…

class Dog:
    def __init__(self, breed):
        self.breed = breed
    def showBreed(self):
        print "It's a %s"%self.breed
    def changeBreed(self, breed):
        self.breed = breed
-----------

And so ends the series. There’s a lot of things I haven’t covered–the __del__ method, polymorphism (having the same method name do something different depending on what class it belongs too), inheritance (I couldn’ve had a Pet superclass, with name, breed, etc. and then Dog and Cat subclasses that inherited methods and attributes from Pet, but had some of their own (i. e. Dog.woof(), Cat.washBody()…) and a bunch of other stuff. But this is really all you need to know to do well–everything else is just very important icing. And there’s certainly enough tutorials out there for that.

Share/Save/Bookmark

7 Responses to “An Object-Oriented Primer in Python: Part 2”

  1. [...] Part 2 to learn how to make classes~ Hello there! If you are new here, you might want to subscribe to [...]

  2. Bob says:

    I had no idea that that is what the self parameter was for. Thanks ;)

  3. Rigo Vides says:

    @Bob, it’s similar to ‘this’ in Java…

    I didn’t understand why the atributes aren’t defined within the class’s code block… They’re only declared as parameters in the class methods. Does this means that once we assign a value with self.foo operator, this foo variable becomes an atribute for the class?

  4. Timmy says:

    @Rigo Yes, self.foo is an attribute.
    If you do this:
    class Whatever(parameter):
    It’ll think that Whatever inherits from parameter.

  5. giorgio says:

    print “It’s a %s”%self.breed
    the # %s”% #
    what does it mean?
    why dont we use print ” It’s a ” + str(self.breed)??

  6. giorgio says:

    class Dog:
    def __init__(self,breed):
    self.breed = breed
    def showBreed(self):
    print “It is a %s”%self.breed
    def changeBreed(self,breed):
    self.breed = breed
    hey = Dog(“Golden”)
    hey.showBreed()
    hey.breed = “LeLe”
    hey.showBreed()
    hey.changeBreed(“LALA”)
    hey.showBreed()
    hey.breed

    this is my code.
    why at the end…the last “hey.breed”…never come out anything?

  7. Timmy says:

    hey.breed is merely an attribute of hey–it’s just the name of a variable that contains a string. To show it, you would have to print it:
    print hey.breed

  8. Can+~ says:

    “print “It’s a %s”%self.breed
    the # %s”% #
    what does it mean?”

    That’s the C-style formatted printing, it’s usually more compact and easier to read when you are working with long texts, or multiple variables, because you can pack everything inside a tuple and just throw it over a syntax, rathern than having to concatenate every variable.

    “Hello %s, in %d days you need to %s” % (“John”, 10, “Take out the trash”)

    Pair that with Dictionaries:

    “Hello %(name)s, in %(days)d days you need to %(task)s” % {“name”:”John”, “days”:3, “task”:”Take out the trash”}

Leave a Reply