46.Classes and Objects in Python- Accessors and mutators

Python is an object-oriented programming language, which means that it provides features that support object-oriented programming.
The basic components of object oriented programming are classes and objects.

A Class is a blue print to create an object. It provides the definition of basic attributes(properties) and functions of objects.

Object is a running instance of the class having the identity(name), properties( values) and behaviors(functions).

The object oriented program thus consist of object definitions (classes) and most of the computations and functions are mentioned as operations on the object.Each object definition corresponds to some object or concept in the real world, and the functions that operate on these object correspond to the ways real-world objects interact.

We have learned objects of string, list, tuple etc…and used the properties and functionalities of these objects which are built into the Python. Now we are going to create our own(user defined) objects.

The class provides basic definitions of an object, which defines the attributes and methods of an object. Methods are defined inside a class definition in order to make the relationship between the class and the method explicit and are called with the object name.

Programmers who use objects and classes know several things
  • The interface or set of methods  that can be used with a class of objects.
  • The attributes of an object that describe its state from the user's point of view.
  • How to instantiate a class to obtain an object.
Like functions, objects are abstractions.A function packages an algorithm in a single operation that can be called by its name.An object packages a set of data values(its state) and set of operations(its methods), in a single entity that can be referenced with a name.This makes an object a more complex abstraction than a function.

A class definition is like a blue print for each of the objects of that class. This blue print contains
  • definitions of all of the methods that its objects recognise
  • descriptions of the data structures used to maintain the state of an object, or its attributes from the implementer's point of view.
Example1:
Lets create a Point class representing a point (x,y) in a two dimensional coordinate system. A point object will have x,y values and also member functions to initialize and print the values.

class Point:
    '''representing a point in xy plane'''
    def __init__(self,x=0,y=0): 
        self.x=x
        self.y=y
    def printpoint(self):
        print("(",self.x,",",self.y,")")
   def __del__(self):
       print("Object deleted')
P1=Point()
P1.printpoint() # will print (0,0)
P2=Point(10,20)
P2.printpoint() # will print ( 10,20)
print(P1. __doc__) # will print docstring '''representing a point in xy plane'''
del P1 # will call the destructor and print Object deleted 

class Point:

will create a namespace for the class Point.

Constructors in Python (Using __init__)
A constructor is a special method that is used to initialize the data members of a class. In python, the built in method __init__ is a sort of constructor. Notice the double underscores both in the beginning and end of init. In fact it is the first method defined for the class and is the first piece of code executed in a newly created instance of the class. The constructor will be executed automatically when the object is created.

Destructors in Python (Using __del__)
The users call Destructor for destroying the object. In Python, developers might not need destructors as much it is needed in the C++ language. This is because Python has a garbage collector whose function is handling memory management automatically.
The __del__() function is used as the destructor function in Python. The user can call the __del__() function when all the references of the object have been deleted, and it becomes garbage collected.The destructor is also called automatically when the program terminated

Methods
Methods are member functions defined inside the class, which gives the functionality. Class methods have only one specific difference from ordinary functions - they must have an extra argument in the beginning of the parameter list. This particular argument is self which is used for referring to the instance. But you need not give any value for this parameter, when you call the method. Self is an instance identifier and is required so that the statements within the methods can have automatic access to the current instance attributes.

Class Instances(Objects)
Having a class defined, you can create as many objects as required. These objects are called instances of this class. The process of creating objects is called instantiation.

All the instances created with a given class will have the same structure and behaviour. They will only differ regarding their state, i.e; regarding the value of their attributes.
To create instances of a class, you call the class using class name and pass in whatever arguments its __init__ method accepts.
In the above example two instance of the class is created. One Point object with default values ie;(0,0) and the other with value (10,20).
P1=Point()
P2=Point(10,20)

Attribute Reference: Accessing attributes of a class
Classes and instances have their own namespaces, that is accessible with the dot ('.') operator.
This is the standard syntax used for all attribute references which is
Object Name. Attribute Name.

As discussed before all the names that were given during the class definition and hence were in the class's namespace are valid attribute names. You access the object's attributes using the dot operator with object as shown in the example above :
P1.printpoint()
P2.printpoint()

Sameness
When you say Hari and I have the same car, you mean that his car and yours are the same make and model, but that they are two different cars.

If you say, “Chris and I have the same mother,” you mean that his mother and yours are the same person. So the idea of “sameness” is different depending on the context.

When you talk about objects, there is a similar ambiguity. For example, if two Points are the same, does that mean they contain the same data (coordinates) or that they are actually the same object?

For example consider the code below
P1=Point(10,20)
P2=Point(10,20)
print(P1==P2)
print(P1 is P2)

It is noted that both print statement will print False even though they contain the same data, they refer to two different objects. If we assign P2=P1, they refer to the same object.
P2=P1
print(P1 is P2)

This will print True because both P1 and P2 is now referring the same object. You can check id(P1) and id(P2).
This type of equality is called shallow equality because it compares only the references, not the contents of the objects.
If you want to compare the actual contents of the object ie; deep equality, we have to write a separate function like this

def compare(P1,P2):
    return (P1.x==P2.x) and (P1.y==P2.y)

Now if we create two different objects that contain the same data, we can use compare(P1,P2) function to find out if they represent the same point.

Example2: The Students class
The course-management application needs to  represent information about students in course.Each student has a name and a list of test scores.We can use these as attributes of a class named Student.The student class should allow the user to view a student's name, view a test score at a given position( counting from 1), reset a test score at a given position, view the highest test score, view the average test score and obtain a string representation of the student's information. When a Student object is created, the user supplies the student's name and the number of test scores. Each score is initially presumed to be zero.
Methods                                                Description
s=Student(name,number)                      Returns a Student object with the given name and number of 
                                                               scores.Each score is initially zero.
s.getName()                                           Returns student's name.
s.getScore(i)                                          Returns student's ith score.
s.setScore(i,score)                                 Set the student's ith score.
s.getAverage()                                       Returns the student's average score.
s.getHighScore()                                   Returns the student's highest score.
s.__str()__                                             Returns the string representation of the students information.

The code for Student class follows
'''
    File: student.py
    resources to manage student's name and test scores.
'''
class Student:
    ''' represents a student '''
    def __init__(self,name,number):
        ''' constructor creates a Student with given name and number of scores and sets all scores to 0'''
        self.name=name
        self.scores=[]
        for count in range(number):
          self.scores.append(0)
    def getName(self):
        ''' returns the student's name '''
        return self.name
    def setScore(self, i , score ):
        '''reset the ith score counting from 1'''
        self.scores[i-1]=score
    def getScore(self, i  ):
        '''reset the ith score counting from 1'''
        return self.scores[i-1]
    def getAverage(self):
        ''' returns the average score '''
        return sum(self.scores)/len(self.scores)
    def getHighScore(self):
        ''' returns the highest score'''
        return max(self.scores)
    def __str__(self):
        ''' return the string representation of student'''
        return "Name:"+ self.name+ "\n Scores:"+" ".join(map(str,self.scores))

>>> from student import Student
>>> s=Student("bvp",5)
>>> print(s)
Name:bvp
 Scores:0 0 0 0 0
>>> s.setScore(1,85)
>>> s.setScore(2,95)
>>> s.setScore(3,75)
>>> s.setScore(4,60)
>>> s.setScore(5,100)
>>> print(s)
Name:bvp
 Scores:85 95 75 60 100
>>> s.getScore(1)
85
>>> s.getHighScore()
100
>>> s.getAverage()
83.0
>>> s.getName()
'bvp'

Docstrings
The first thing to note is the positioning of the docstrings in the code.They can occure at three levels.The first level is that of module. The second level is just after the class header.The third level is located after each method header.When you enter help(Student) at a shell prompt, the interpreter prints the documentation for the class and all of its methods.

Method Definitions
All of the method definitions are indented below the class header.Methods are functions with a first parameter named self, even if that method seems to expect no arguments when called.When a method is called with an object, the interpreter binds the parameter self to that object so that the method's code can refer to the object by name.

The __init__ method and instance variables
Most classes include a special method named __init__.Note that __init__ must begin and end with two consecutive underscores. This method is also called the class's constructor, because it is run automatically when a user instantiates the class. Thus when we run

s=Student("Fathima",5)

Python automatically runs the constructor or __init__ method of the Student class.The purpose of the constructor is to initialize an individual object's attribute.

The attributes of an object are represented as instance variables.Each individual object has its own set of instance variables. These variables serve as storage for its state. The scope of an instance variable is the entire class definition.The lifetime of an instance variable is the lifetime of the enclosing object.Within the class definition, the names of the instance variables must begin with self.
eg: self.name

The __str__ method
Many built-in Python classes usually include an __str__ method. This method builds and returns a string representation of an object's state.When the str function is called with an object, that object's __str__ method is automatically invoked to obtain the string that str returns.The function print(s) also automatically runs str(s) to obtain the objects string representation for output.

Accessors and Mutators
Methods that allow a user to observe but not change the state of an object are called accessors.Methods that allow a user to modify an object's state are called mutators. The Students class has just one mutator method. It allows the user to reset a test score at a given position.
def setScore(self, i , score ):
        '''reset the ith score counting from 1'''
        self.scores[i-1]=score

Lifetime of Objects
An object is created when the class is instantiated.An object will die when the program that created it can no longer refer to it.
>>>x=[s]
>>> s
<student.Student object at 0x02035478>
>>> x
[<student.Student object at 0x02035478>]
The above will create a reference x to the object s.As long as one of these reference survives, the Student object can remain alive. Even if we set s=None and x=None, the student object still exist, but the Python machine will eventually recycle its storage during a process called garbage collection and its storage will be used to create other objects.

Rules of Thumb for Defining a Simple Class

1.Think about the behaviour and attributes of the objects of the new class.What actions does an object perform and how these actions access or modify objects state.
2. Design and test the class with appropriate class name and methods with parameters.
3.Choose appropriate data structures to represent the attributes of the class.
4.Fill in the class template with a constructor ( an __init__) method and an __str__ method. Instantiate object and test the object by printing.
5.Define the methods by incrementally working in a bottom-up manner.If one method depends on the other, complete the second one first.
6.Document the code.Include a docstring for the module, the class and each method.

Comments

Popular posts from this blog

Python For Machine Learning - CST 283 - KTU Minor Notes- Dr Binu V P

KTU Python for machine learning Sample Question Paper and Answer Key Dec 2020