[Tutor] Class Construction question [C++ and Python class introduction]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Wed Nov 13 01:42:03 2002


> 	I have a question, which I hope is not real stupid, but here goes
> anyway. I am trying to construct some classes and I am starting with a
> real basic Person class. Which holds name, address, and telephone
> number. Here is what I have so far:


Hi Chris,

A few people have written you back about how to correct your code, so I
probably don't need to repeat them.  *grin*


But you mentioned that you had some experience with C++, so I thought it
might be useful to compare the way that Python does classes with the way
C++ does them.

Like C++, Python's classes have a default "constructor" that doesn't do
anything if we don't define one:

###
>>> class Book:
...     def title(self):
...         return "Huckleberry Finn"
...
>>> Book()
<__main__.Book instance at 0x8156774>
>>> b = Book()
>>> b.title()
'Huckleberry Finn'
###

Like C++, we can override this default by defining exactly what new
instances of a class should look like.  Unlike C++, we don't reuse the
name of the class as the name of the constructor, but instead use the
special method name '__init__':

###
>>> class Book:
...     def __init__(self, title):
...         self.title = title
...     def getTitle(self):
...         return self.title
...
>>> b = Book("A Boy's Will")
>>> b.getTitle()
"A Boy's Will"
###



Also, unlike C++, there's just one "namespace" for both methods and
attributes.  There's a unity to this approach, a uniform way of getting at
both methods and "regular" attribute values:

###
>>> b.title
"A Boy's Will"
>>> b.getTitle
<bound method Book.getTitle of <__main__.Book instance at 0x8155ecc>>
###

But at the same time, we've have to be careful that we don't name our
methods the same as our attributes; otherwise, we're bound to munge
something up:

###
>>> class BadBook:
...     def __init__(self, title):
...         self.title = title
...     def title(self):
...         return self.title
...
>>> b = BadBook("The Lion, the Witch, and the Warddrobe")
>>> b.title
'The Lion, the Witch, and the Warddrobe'
>>> b.title()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: 'str' object is not callable
###

Oops.

So by convention, we often put a single understore in front of our
attribute names.  It sounds a bit informal, but it works pretty well!

###
>>> class Book:
...     def __init__(self, title):
...         self._title = title
...     def title(self):
...         return self._title
...
>>> b = Book("generatingfunctionology")
>>> b.title()
'generatingfunctionology'
###



Like C++, we do have ways of overloading operators like '+' and '%' to
work with our instances.  But just like the case with the constructor
name, Python's object system uses other "special method names" that we can
override to make operator overloading happen.  If we're interested, we can
take a look at:

    http://python.org/doc/current/ref/specialnames.html


Let's take a simple number class, and end by converting it to Python:

//////
#include <iostream>

class Number {
public:
    Number(int value) {
        this->value = value;
    }
    Number operator+(Number& other) {
        return Number(other.value + this->value);
    }
    friend ostream& operator<<(ostream &output, const Number &num) {
	output << num.value;
	return output;
    }
private:
    int value;
};

int main() {
  Number three(3);
  Number four(4);
  cout << "three plus four is " << three + four << "\n";
  return 0;
}
//////



Here's an equivalent translation of this C++ number class to Python:

###
import sys

class Number:
    def __init__(self, value):
        self._value = value

    def __add__(self, other):
        return Number(self._value + other._value)

    def __str__(self):
        return str(self._value)

if __name__ == '__main__':
    three = Number(3)
    four = Number(4)
    print "three plus four is", three + four
    sys.exit(0)
###


By the way, just to make it clear: Python's 'sys' and C++'s 'iostream' are
NOT equivalent, although we can see some similarities in the way both
languages provide access to their respective standard libraries.  I had to
import 'sys' in the Python version in order to use the sys.exit()
function, just as I had to include 'iostream' in order to use the 'cout'
character output stream.

(It's been a while since I typed C++ code in; I hope it didn't come out
too awkwardly!  *grin*)


I hope some of this information is helpful!  Please feel free to ask more
questions as they come up.