Classes in Python

Classes and objects are the two main aspecs of object oriented programming. A class creates a new type where objects are instances of the class.

Objects can store data using ordinary variables that belong to the object. Variables that belong to an object or class are called as fields. Objects can also have functionality by using functions that belong to a class. Such functions are called methods of the class. This terminology is important because it helps us to differentiate between functions and variables which are separate by itself and those which belong to a class or object. Collectively, the fields and methods can be referred to as the attributes of that class.

1 The self

Class methods have only one specific difference from ordinary functions - they must have an extra first name that has to be added to the beginning of the parameter list, but you do not give a value for this parameter when you call the method, Python will provide it. This particular variable refers to the object itself, and by convention, it is given the name self.

2 The init method

There are many method names which have special significance in Python classes. We will see the significance of the __init__ method now. The __init__ method is run as soon as an object of a class is instantiated. The method is useful to do any initialization you want to do with your object.

class Human(object):
    def __init__(self, name):
        self.name = name
    def sayHi(self):
        '''Greeting by the person.
        Really, that's all it does.'''
        print('Hi, my name is %s.' % self.name)
human_j = Human("John")
human_j.sayHi()
## Hi, my name is John.
human_j.name='Jack'
human_j.sayHi()
## Hi, my name is Jack.

3 accees control

We see from last example name attribute can be easily modified. We can add two underline __name to control access.

class Human(object):
    def __init__(self, name):
        self.__name = name
    def walk(self):
        print(self.name + " is walking")
    def get_name(self):
        return self.__name
    def set_name(self, name):
        self.__name = name
human_a = Human("Alan")
print(human_a.get_name())
## Alan
human_a.set_name("Alex")
print(human_a.get_name())
## Alex

4 Class variables and Object variables

There are two types of fields - which are classified depending on whether the class or the object owns the variables respectively.

Class variables are shared in the sense that they are accessed by all objects (instances) of that class. There is only copy of the class variable and when any one object makes a change to a class variable, the change is reflected in all the other instances as well.

Object variables are owned by each individual object/instance of the class. In this case, each object has its own copy of the field i.e. they are not shared and are not related in any way to the field by the samen name in a different instance of the same class. An example will make this easy to understand.

class Robot:
    '''Represents a robot, with a name.'''
    #A class variable, counting the number of robots
    population = 0
    def __init__(self,name):
        '''Initializes the data.'''
        self.name = name
        print('(Initialize {0})'.format(self.name))
        # When this person is created, the robot 
        # adds to the population 
        Robot.population += 1
    def __del__(self):
        '''I am dying.'''
        print('{0} is being destroyed!'.format(self.name))
        Robot.population -= 1
        if Robot.population == 0:
            print('{0} was the last one.'.format(self.name))
        else:
            print('There are still {0:d} robots working.'.format(Robot.population))
    def sayHi(self):
        '''Greeting by the robot.
        Yeah, they can do that.'''
        print('Greetings, my master call me {0}.'.format(self.name))
    def howMany():
        '''Prints the current population.'''
        print('We have {0:d} robots.'.format(Robot.population)) 
    howMany = staticmethod(howMany)
    
droid1 = Robot('R2-D2')
## (Initialize R2-D2)
droid1.sayHi()
## Greetings, my master call me R2-D2.
Robot.howMany()
## We have 1 robots.
droid2 = Robot('C-3P0')
## (Initialize C-3P0)
droid2.sayHi()
## Greetings, my master call me C-3P0.
Robot.howMany()
## We have 2 robots.
print("Robots have finished their work. So let's destroy them.")
## Robots have finished their work. So let's destroy them.
del droid1
## R2-D2 is being destroyed!
## There are still 1 robots working.
del droid2
## C-3P0 is being destroyed!
## C-3P0 was the last one.
Robot.howMany()
## We have 0 robots.

5 Inheritance

One of the major benefits of object oriented programming is reuse of code and one of the ways this is achieved is through the inheritance mechanism. Inheritance can be best imagined as implementing a type and subtype relationship between classes.

class SchoolMember:
        '''Represents any school member.'''
        def __init__(self, name, age):
                self.name = name
                self.age = age
                print('(Initialized SchoolMember: %s)' % self.name)
        def tell(self):
                '''Tell my details.'''
                print('Name:"%s" Age:"%s"' % (self.name, self.age))
class Teacher(SchoolMember):
        '''Represents a teacher.'''
        def __init__(self, name, age, salary):
                SchoolMember.__init__(self, name, age)
                self.salary = salary
                print ('(Initialized Teacher: %s)' % self.name)
        def tell(self):
                SchoolMember.tell(self)
                print ('Salary: "%d"' % self.salary)
class Student(SchoolMember):
        '''Represents a student.'''
        def __init__(self, name, age, marks):
                SchoolMember.__init__(self, name, age)
                self.marks = marks
                print ('(Initialized Student: %s)' % self.name)
        def tell(self):
                SchoolMember.tell(self)
                print ('Marks: "%d"' % self.marks)
t = Teacher('Mr Byte', 40, 30000)
## (Initialized SchoolMember: Mr Byte)
## (Initialized Teacher: Mr Byte)
s = Student('Mike', 22, 75)
## (Initialized SchoolMember: Mike)
## (Initialized Student: Mike)
members = [t, s]
for member in members:
        member.tell() # works for both Teachers and Students
## Name:"Mr Byte" Age:"40"
## Salary: "30000"
## Name:"Mike" Age:"22"
## Marks: "75"