Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
122 views

OOP With Python

This is the material for object-oriented programming with python which includes all the required topics.

Uploaded by

Hetvi Patel
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
122 views

OOP With Python

This is the material for object-oriented programming with python which includes all the required topics.

Uploaded by

Hetvi Patel
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

Object Oriented Programming

Python is an object-oriented programming language. Due to that creation and usage of class
and object is very much easy. You can implement any of the OOP concepts using python.

1. Terminologies:
• Class: A user-defined prototype for an object that defines a set of attributes that
characterise any object of the class. The attributes are data members (class variables
and instance variables) and methods, accessed via dot notation.
• Data member: A class variable or instance variable that holds data associated with a
class and its objects.
• Class variable: A variable that is shared by all instances of a class.
• Instance: An individual object of a certain class. An object obj that belongs to a class
Circle, for example, is an instance of the class Circle.
• Instance variable: A variable that is defined inside a method and belongs only to the
current instance of a class.
• Instantiation: The creation of an instance of a class.
• Method: − A special kind of function that is defined in a class definition.
• Inheritance: − The transfer of the characteristics of a class to other classes that are
derived from it.
• Function overloading: The assignment of more than one behaviour to a particular
function. The operation performed varies by the types of objects or arguments
involved.
• Operator overloading: The assignment of more than one function to a particular
operator.

2. Class and object:


• The class statement creates a new class definition. The name of the class immediately
follows the keyword class followed by a colon as follows:
class ClassName:
'Optional class documentation string'
class_suite

• The class has a documentation string, which can be accessed via ClassName.__doc__.
• The class_suite consists of all the component statements defining class members, data
attributes and functions.

1
• Classes support multiple copies. This is because classes have two different objects:
class objects and instance objects.
• Instance objects are normally marked by the keyword self, so a class method could be
Employee.Display() while a specific instance of the Display() method would be marked
as self.Display().
• Each instance object has its own namespace but also inherits from the base class
object.
• Classes can define objects that respond to the same operations as built-in types.

Example 1:
class MyClass:
variable = "Hello"
def function(self):
print('Inside Class')

print(MyClass)

Output:
<class '__main__.MyClass'>

❖ Delete Object Properties


We can delete properties on objects by using the del keyword:
del e1.age

❖ Delete Object
We can delete objects by using the del keyword
del e1

Example 2:
class Employee:
'Common base class for all employees'
empCount = 0
age=10

def __init__(self, name, salary):


self.name = name
self.salary = salary
Employee.empCount += 1

def displayCount(self):

2
print("Total Employee %d" %Employee.empCount)

def displayEmployee(self):
print("Name : ", self.name, ", Salary: ", self.salary
)

e1=Employee("Hetal",50000)
e1.displayCount()
e1.displayEmployee()
e2=Employee("Ved",45000)
e2.displayCount()
e2.displayEmployee()

e1.age = 8 # Modify 'age' attribute.


print("Age of e1 :",e1.age)
del e1.age #Delete 'age' attribute.

Output:
Total Employee 1
Name :Hetal , Salary: 50000
Total Employee 2
Name :Ved , Salary: 45000
Age of e1 : 8

• The first method __init__() is a special method, which is called class constructor or
initialization method that Python calls when you create a new instance of this class.
• Python adds the self argument to the list for you; you do not need to include it when
you call the methods.
• All classes have a function called __init__(), which is always executed when the class is
being initiated.
• Use the __init__() function to assign values to object properties, or other operations
that are necessary to do when the object is being created:
In example 2,
• The variable empCount is a class variable whose value is shared among all instances of
a this class. This can be accessed using an object of a class from inside the class or
outside the class.
• The first method __init__() is a special method, which is called class constructor or
initialisation method that Python calls when you create a new instance of this class.
Note: The __init__() function is called automatically every time the class is being used to
create a new object.

3
❖ The self Parameter
• The self parameter is a reference to the current instance of the class, and is used to
access variables that belongs to the class.
• It does not have to be named self , you can call it whatever you like, but it has to be
the first parameter of any function in the class:

Example 3:
class Person:
def __init__(myobj, name, age):
myobj.name = name
myobj.age = age

def func(x):
print("My name is " + x.name)

p1 = Person("Heta", 30)
p1.func()

Output:
My name is Heta

Note: The self parameter is a reference to the current instance of the class, and is used to
access variables that belong to the class.

❖ Built-In Class Attributes:


Every Python class keeps following built-in attributes and they can be accessed using dot
operator like any other attribute −
• __dict__: Dictionary containing the class's namespace.
• __doc__: Class documentation string or none, if undefined.
• __name__: Class name.
• __module__: Module name in which the class is defined.
• This attribute is "__main__" in interactive mode.
• __bases__: A possibly empty tuple containing the base classes, in the order of their
occurrence in the base class list.

Example 4:
class Employee:
'Common base class for all employees'
empCount = 0

def __init__(self, name, salary):

4
self.name = name
self.salary = salary
Employee.empCount += 1

def displayCount(self):
print("Total Employee %d",Employee.empCount)

def displayEmployee(self):
print("Name : ", self.name, ", Salary: ", self.salary
)

print("Employee.__doc__:", Employee.__doc__)
print("Employee.__name__:", Employee.__name__)
print("Employee.__module__:", Employee.__module__)
print("Employee.__bases__:", Employee.__bases__)
print("Employee.__dict__:", Employee.__dict__)

Output:
Employee.__doc__: Common base class for all employees
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: (<class 'object'>,)
Employee.__dict__: {'__module__': '__main__', '__doc__':
'Common base class for all employees', 'empCount': 0,
'__init__': <function Employee.__init__ at 0x7f63c2522200>,
'displayCount': <function Employee.displayCount at
0x7f63c2522dd0>, 'displayEmployee': <function
Employee.displayEmployee at 0x7f63c2522440>, '__dict__':
<attribute '__dict__' of 'Employee' objects>, '__weakref__':
<attribute '__weakref__' of 'Employee' objects>}

❖ The pass Statement


class definitions cannot be empty, but if you for some reason have a class definition with no
content, put in the pass statement to avoid getting an error.
class Employee:
Pass

5
3. Inheritance
Inheritance allows us to define a class that inherits all the methods and properties from
another class.
Parent class is the class being inherited from, also called base class.
Child class is the class that inherits from another class, also called derived class.
class BaseClass:
Body of base class
class DerivedClass(BaseClass):
Body of derived class

Example 5:
class Parent: # define parent class
parentAttr = 100
def __init__(self):
print("Calling parent constructor")

def parentMethod(self):
print('Calling parent method')

def setAttr(self, attr):


Parent.parentAttr = attr

def display(self):
print("Parent attribute :", Parent.parentAttr)

class Child(Parent): # define child class


def __init__(self):
print ("Calling child constructor")

def childMethod(self):
print('Calling child method')

A=Parent()
B=Child()
A.parentMethod()
B.childMethod()
B.parentMethod()
B.setAttr(10)
B.display()

Output:
Calling parent constructor
Calling child constructor
Calling parent method

6
Calling child method
Calling parent method
Parent attribute : 10

❖ Multiple Parent Class

You can drive a class from multiple parent classes


class A: # define your class A
.....
class B: # define your class B
.....
class C(A, B): # subclass of A and B
.....

Example 6:
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname

def printname(self):
print(self.firstname, self.lastname)

class Student(Person):
pass

Output:
Hetal Patel

❖ Add the __init__() Function


• When you add the __init__() function, the child class will no longer inherit the parent's
__init__() function.
• To keep the inheritance of the parent's __init__() function, add a call to the parent's
__init__() function:
Note: The child's __init__() function overrides the inheritance of the parent's __init__()
function.

Example 7:
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname
print("Initialization in Parent Class")

7
def printname(self):
print(self.firstname, self.lastname)

class Student(Person):
def __init__(self, fname, lname):
Person.__init__(self, fname, lname)

x = Student("Hetal", "Patel")
x.printname()

Output:
Initialization in Parent Class
Hetal Patel

❖ super() Function
Python also has a super() function that will make the child class inherit all the methods and
properties from its parent:
By using the super() function, you do not have to use the name of the parent element, it will
automatically inherit the methods and properties from its parent.

Example 8:
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname

def printname(self):
print(self.firstname, self.lastname)

class Student(Person):
def __init__(self, fname, lname, year):
super().__init__(fname, lname)
self.graduationyear = year

def welcome(self):
print("Welcome", self.firstname, self.lastname, "to the
class of", self.graduationyear)

x = Student("Ved", "Shah", 2021)


x.welcome()

Output:

Welcome Ved Shah to the class of 2021

8
❖ Overriding Methods

When the method is defined in both classes (Base class and derived class) then the method
in the derived class overrides that in the base class.

• Generally when overriding a base method, we tend to extend the definition rather
than simply replace it. The same is being done by calling the method in base class
from the one in derived class (calling Person.__init__() from __init__() in Student).
• A better option would be to use the built-in function super().

Two built-in functions isinstance() and issubclass() are used to check inheritances.
• The function isinstance() returns True if the object is an instance of the class or other
classes derived from it.
• Each and every class in Python inherits from the base class object.

Example 9:
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname

def printname(self):
print(self.firstname, self.lastname)

class Student(Person):
def __init__(self, fname, lname):
super().__init__(fname, lname)

x = Student("Ved", "Shah")
x.printname()
y = Person("Saloni","Patel")
y.printname()

print("\nUse of isinstance()")
print(isinstance(x,Student))
print(isinstance(x,Person))
print(isinstance(x,object))
print(isinstance(y,Student))

# issubclass() is used to check for class inheritance.


print("\nUse of issubclass()")
print(issubclass(Student,Person))
print(issubclass(Person,Student))

9
Output:
Ved Shah
Saloni Patel

Use of isinstance()
True
True
True
False

Use of issubclass()
True
False

4. Operator Overloading
• The assignment of more than one function to a particular operator.
• You can change the meaning of an operator in Python depending upon the operands
used.
• Python operators work for built-in classes. But the same operator behaves differently
with different types.
• This feature in Python that allows the same operator to have different meaning
according to the context is called operator overloading.

❖ Python Special Functions


• Class functions that begin with double underscore __ are called special functions in
Python.
• These functions are not the typical functions that we define for a class.
• Using special functions, we can make our class compatible with built-in functions.

❖ Overloading the + Operator


To overload the + operator, we will need to implement __add__() function in the class.

Example 10:

#Addition of Two points p1 and p2

class Addition:

10
def __init__(self, x=0, y=0):
self.x = x
self.y = y

def __str__(self):
return "({0},{1})".format(self.x, self.y)

def __add__(self, other):


x = self.x + other.x
y = self.y + other.y
return Addition(x, y)

p1 = Addition(10, 20)
p2 = Addition(10, 50)

print("Addition of Two Points on 2D = ",p1+p2)

Output:
Addition of Two Points on 2D = (20,70)

Here in above Example, when you use p1 + p2, Python calls p1.__add__(p2) which in turn is
Addition.__add__(p1,p2).

The special function that we need to implement is tabulated below.

Operator Expression Internally

Addition p1 + p2 p1.__add__(p2)

Subtraction p1 - p2 p1.__sub__(p2)

Multiplication p1 * p2 p1.__mul__(p2)

Power p1 ** p2 p1.__pow__(p2)

Division p1 / p2 p1.__truediv__(p2)

Floor Division p1 // p2 p1.__floordiv__(p2)

Remainder (modulo) p1 % p2 p1.__mod__(p2)

Bitwise Left Shift p1 << p2 p1.__lshift__(p2)

11
Bitwise Right Shift p1 >> p2 p1.__rshift__(p2)

Bitwise AND p1 & p2 p1.__and__(p2)

Bitwise OR p1 | p2 p1.__or__(p2)

Bitwise XOR p1 ^ p2 p1.__xor__(p2)

Bitwise NOT ~p1 p1.__invert__()

❖ Overloading Comparison Operators


Example 11:
#Overloading of < operator
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y

def __str__(self):
return "({0},{1})".format(self.x, self.y)

def __lt__(self, other):


self_mag = (self.x ** 2) + (self.y ** 2)
other_mag = (other.x ** 2) + (other.y ** 2)
return self_mag < other_mag

p1 = Point(1,1)
p2 = Point(-2,-3)
p3 = Point(1,-1)

# use less than


print(p1<p2)
print(p2<p3)
print(p1<p3)

Output:
True
False
False

12
To overload other comparison operators are tabulated below.

Operator Expression Internally

Less than p1 < p2 p1.__lt__(p2)

Less than or equal to p1 <= p2 p1.__le__(p2)

Equal to p1 == p2 p1.__eq__(p2)

Not equal to p1 != p2 p1.__ne__(p2)

Greater than p1 > p2 p1.__gt__(p2)

Greater than or equal to p1 >= p2 p1.__ge__(p2)

5. Data Hiding
• An object's attributes may or may not be visible outside the class definition.
• You need to name attributes with a double underscore prefix, and those attributes
then are not be directly visible to outsiders.

Example 12:
class JustCounter:
__secretCount = 0

def count(self):
self.__secretCount += 1
print(self.__secretCount)

counter = JustCounter()
counter.count()
counter.count()
print(counter.__secretCount) # Error in the line

Output:
1
2
AttributeError: 'JustCounter' object has no attribute
'__secretCount'

13
• Python protects those members by internally changing the name to include the class
name.
• You can access such attributes as object._className__attrName.
• So modified code is for Example 12 is given in example 13

Example 13:
class JustCounter:
__secretCount = 0

def count(self):
self.__secretCount += 1
print(self.__secretCount)

counter = JustCounter()
counter.count()
counter.count()
print(counter._JustCounter__secretCount)

Output:
1
2
2

6. Multithreading
• Multiple threads within a process share the same data space with the main thread and
can therefore share information or communicate with each other more easily than if
they were separate processes.
• Threads sometimes called light-weight processes and they do not require much
memory overhead; they are cheaper than processes.
• It can be pre-empted (interrupted)
• It can temporarily be put on hold (also known as sleeping) while other threads are
running - this is called yielding.

❖ Benefits of Threading
• For a single process, multiple threads can be used to process and share the same data-
space and can communicate with each other by sharing information.
• They use lesser memory overhead, and hence they are called lightweight processes.
• A program can remain responsive to input when threads are used.
• Threads can share and process the global variable's memory.
In a thread, there are three different parts. It has the beginning, an execution part, and a
conclusion. It also has an instruction pointer that points to where the thread or process is

14
currently running, and hence the thread can run several different program blocks
concurrently.

❖ Using a New Thread


Syntax:
thread.start_new_thread(function, args[, kwargs])

Here, the first part is a method & this method is a faster and more efficient way to create
new threads. As the child thread starts, the function passes a list of args. The thread gets
terminated when the function returns a value.
The 'args' in the above syntax is a tuple of arguments.

❖ Methods of Thread Class


The threading module, as described earlier, has a Thread class that is used for implementing
threads, and that class also contains some predefined methods used by programmers in
multi-threaded programming. These are:
• run(): It acts as the entry of the thread
• start(): is used for starting the thread by calling the run()
• isAlive(): is used to verify whether the still executing or not
• getName(): is used for returning the name of a thread
• setName(): is used to set the name of the thread

15

You might also like