Python Lab manual 05
Python Lab manual 05
Objectives:
➢ To learn and able to create class, constructor and object
➢ To learn and able to create instance variable, class variable and member functions
➢ learn and able to use encapsulation (public, private and protected)
➢ To learn and able to use setter and getter
Outcomes:
➢
Students should be able to create class, constructor and object
➢ Students should be able to create instance variable, class variable and member functions
➢ Students should be able to use encapsulation (public, private and protected)
➢ Students should be able to use setter and getter
5.1 OOP
Object-oriented programming (OOP) is a method of structuring a program by bundling related properties and behaviors into
individual objects. In this tutorial, you’ll learn the basics of object-oriented programming in Python.
Conceptually, objects are like the components of a system. Think of a program as a factory assembly line of sorts. At each
step of the assembly line a system component processes some material, ultimately transforming raw material into a finished
product.
Object-oriented programming is a programming paradigm that provides a means of structuring programs so that properties
and behaviors are bundled into individual objects.
For instance, an object could represent a person with properties like a name, age, and address and behaviors such as walking,
talking, breathing, and running. Or it could represent an email with properties like a recipient list, subject, and body and
behaviors like adding attachments and sending.
Put another way, object-oriented programming is an approach for modeling concrete, real-world things, like cars, as well as
relations between things, like companies and employees, students and teachers, and so on. OOP models real-world entities
as software objects that have some data associated with them and can perform certain functions.
Another common programming paradigm is procedural programming, which structures a program like a recipe in that it
provides a set of steps, in the form of functions and code blocks, that flow sequentially in order to complete a task.
The key takeaway is that objects are at the center of object-oriented programming in Python, not only representing the data,
as in procedural programming, but in the overall structure of the program as well.
pg. 1
Primitive data structures—like numbers, strings, and lists—are designed to represent simple pieces of information, such as
the cost of an apple, the name of a poem, or your favorite colors, respectively. What if you want to represent something
more complex?
For example, let’s say you want to track employees in an organization. You need to store some basic information about
each employee, such as their name, age, position, and the year they started working.
First, it can make larger code files more difficult to manage. If you reference kirk[0] several lines away from where the kirk
list is declared, will you remember that the element with index 0 is the employee’s name?
Second, it can introduce errors if not every employee has the same number of elements in the list. In the mccoy list above,
the age is missing, so mccoy[1] will return "Chief Medical Officer" instead of Dr. McCoy’s age.
A great way to make this type of code more manageable and more maintainable is to use classes.
Classes are used to create user-defined data structures. Classes define functions called methods, which identify the behaviors
and actions that an object created from the class can perform with its data.
In this tutorial, you’ll create a Dog class that stores some information about the characteristics and behaviors that an
individual dog can have.
A class is a blueprint for how something should be defined. It doesn’t actually contain any data. The Dog class specifies
that a name and an age are necessary for defining a dog, but it doesn’t contain the name or age of any specific dog.
While the class is the blueprint, an instance is an object that is built from a class and contains real data. An instance of the
Dog class is not a blueprint anymore. It’s an actual dog with a name, like Miles, who’s four years old.
Put another way, a class is like a form or questionnaire. An instance is like a form that has been filled out with information.
Just like many people can fill out the same form with their own unique information, many instances can be created from a
single class.
All class definitions start with the class keyword, which is followed by the name of the class and a colon. Any code that is
indented below the class definition is considered part of the class’s body.
The Dog class isn’t very interesting right now, so let’s spruce it up a bit by defining some properties that all Dog objects
should have. There are a number of properties that we can choose from, including name, age, coat color, and breed. To keep
things simple, we’ll just use name and age.
The properties that all Dog objects must have are defined in a method called .__init__(). Every time a new Dog object is
created, .__init__() sets the initial state of the object by assigning the values of the object’s properties. That is, .__init__()
initializes each new instance of the class.
You can give .__init__() any number of parameters, but the first parameter will always be a variable called self. When a
new class instance is created, the instance is automatically passed to the self parameter in .__init__() so that new attributes
can be defined on the object.
Let’s update the Dog class with an .__init__() method that creates .name and .age attributes:
Notice that the .__init__() method’s signature is indented four spaces. The body of the method is indented by eight spaces.
This indentation is vitally important. It tells Python that the .__init__() method belongs to the Dog class.
In the body of .__init__(), there are two statements using the self variable:
• self.name = name creates an attribute called name and assigns to it the value of the name parameter.
• self.age = age creates an attribute called age and assigns to it the value of the age parameter.
Attributes created in .__init__() are called instance attributes. An instance attribute’s value is specific to a particular instance
of the class. All Dog objects have a name and an age, but the values for the name and age attributes will vary depending on
the Dog instance.
On the other hand, class attributes are attributes that have the same value for all class instances. You can define a class
attribute by assigning a value to a variable name outside of .__init__().
For example, the following Dog class has a class attribute called species with the value "Canis familiaris":
pg. 3
Class attributes are defined directly beneath the first line of the class name and are indented by four spaces. They must
always be assigned an initial value. When an instance of the class is created, class attributes are automatically created and
assigned to their initial values.
Use class attributes to define properties that should have the same value for every class instance. Use instance attributes for
properties that vary from one instance to another.
Creating a new object from a class is called instantiating an object. You can instantiate a new Dog object by typing the name
of the class, followed by opening and closing parentheses:
You now have a new Dog object at 0x106702d30. This funny-looking string of letters and numbers is a memory address
that indicates where the Dog object is stored in your computer’s memory. Note that the address you see on your screen will
be different.
The new Dog instance is located at a different memory address. That’s because it’s an entirely new instance and is
completely unique from the first Dog object that you instantiated.
pg. 4
In this code, you create two new Dog objects and assign them to the variables a and b. When you compare a and b using the
== operator, the result is False. Even though a and b are both instances of the Dog class, they represent two distinct objects
in memory.
Now create a new Dog class with a class attribute called .species and two instance attributes called .name and .age:
To instantiate objects of this Dog class, you need to provide values for the name and age. If you don’t, then Python raises a
TypeError:
To pass arguments to the name and age parameters, put values into the parentheses after the class name:
pg. 5
This creates two new Dog instances—one for a nine-year-old dog named Buddy and one for a four-year-old dog named
Miles.
The Dog class’s .__init__() method has three parameters, so why are only two arguments passed to it in the example?
When you instantiate a Dog object, Python creates a new instance and passes it to the first parameter of .__init__(). This
essentially removes the self parameter, so you only need to worry about the name and age parameters.
After you create the Dog instances, you can access their instance attributes using dot notation:
One of the biggest advantages of using classes to organize data is that instances are guaranteed to have the attributes you
expect. All Dog instances have .species, .name, and .age attributes, so you can use those attributes with confidence knowing
that they will always return a value.
Although the attributes are guaranteed to exist, their values can be changed dynamically:
In this example, you change the .age attribute of the buddy object to 10. Then you change the .species attribute of the miles
object to "Felis silvestris", which is a species of cat. That makes Miles a pretty strange dog, but it is valid Python!
The key takeaway here is that custom objects are mutable by default. An object is mutable if it can be altered dynamically.
For example, lists and dictionaries are mutable, but strings and tuples are immutable.
Instance methods are functions that are defined inside a class and can only be called from an instance of that class. Just like
.__init__(), an instance method’s first parameter is always self.
pg. 6
Open a new editor window in IDLE and type in the following Dog class:
• .description() returns a string displaying the name and age of the dog.
• .speak() has one parameter called sound and returns a string containing the dog’s name and the sound the dog makes.
Save the modified Dog class to a file called dog.py and run the program. Then open the interactive window and type the
following to see your instance methods in action:
In the above Dog class, .description() returns a string containing information about the Dog instance miles. When writing
your own classes, it’s a good idea to have a method that returns a string containing useful information about an instance of
the class. However, .description() isn’t the most Pythonic way of doing this.
When you create a list object, you can use print() to display a string that looks like the list:
Let’s see what happens when you print() the miles object:
pg. 7
When you print(miles), you get a cryptic looking message telling you that miles is a Dog object at the memory address
0x00aeff70. This message isn’t very helpful. You can change what gets printed by defining a special instance method called
.__str__().
In the editor window, change the name of the Dog class’s .description() method to .__str__():
Methods like .__init__() and .__str__() are called dunder methods because they begin and end with double underscores.
There are many dunder methods that you can use to customize classes in Python. Although too advanced a topic for a
beginning Python book, understanding dunder methods is an important part of mastering object-oriented programming in
Python.
In the next section, you’ll see how to take your knowledge one step further and create classes from other classes.
Encapsulation is one of the fundamental concepts in object-oriented programming (OOP), including abstraction, inheritance,
and polymorphism. This lesson will cover what encapsulation is and how to implement it in Python.
• Encapsulation in Python
• Need for Encapsulation
• Data Hiding using public, protected, and private members
• Data Hiding vs. Encapsulation
• Getter and Setter Methods
• Benefits of Encapsulation
pg. 8
Example:
In this example, we create an Employee class by defining employee attributes such as name and salary as an instance variable
and implementing behavior using work() and show() instance methods.
Using encapsulation, we can hide an object’s internal representation from the outside. This is called information hiding.
Also, encapsulation allows us to restrict accessing variables and methods directly and prevent accidental data modification
by creating private data members and methods within a class.
Encapsulation is a way to can restrict access to methods and variables from outside of class. Whenever we are working with
the class and dealing with sensitive data, providing access to all variables used within the class is not a good choice.
For example, Suppose you have an attribute that is not visible from the outside of an object and bundle it with methods that
provide read or write access. In that case, you can hide specific information and control access to the object’s internal state.
Encapsulation offers a way for us to access the required variable without providing the program full-fledged access to all
variables of a class. This mechanism is used to protect the data of an object from other objects.
pg. 9
Encapsulation can be achieved by declaring the data members and methods of a class either as private or protected. But In
Python, we don’t have direct access modifiers like public, private, and protected. We can achieve this by using single
underscore and double underscores.
Access modifiers limit access to the variables and methods of a class. Python provides three types of access modifiers
private, public, and protected.
Public data members are accessible within and outside of a class. All member variables of the class are by default public.
Example:
pg. 10
5.7.2 Private Member
We can protect variables in the class by marking them private. To define a private variable add two underscores as a prefix
at the start of a variable name.
Private members are accessible only within the class, and we can’t access them directly from the class objects.
Example:
In the above example, the salary is a private variable. As you know, we can’t access the private variable from the outside of
that class.
We can access private members from outside of a class using the following two approaches
pg. 11
5.7.4 Name Mangling to access private members
We can directly access private and protected variables from outside of a class through name mangling. The name mangling
is created on an identifier by adding two leading underscores and one trailing underscore, like this
_classname__dataMember, where classname is the current class, and data member is the private variable name.
Protected members are accessible within the class and also available to its sub-classes. To define a protected member, prefix
the member name with a single underscore _.
pg. 12
Protected data members are used when you implement inheritance and want to allow data members access to only child
classes.
To implement proper encapsulation in Python, we need to use setters and getters. The primary purpose of using getters and
setters in object-oriented programs is to ensure data encapsulation. Use the getter method to access data members and the
setter methods to modify the data members.
In Python, private variables are not hidden fields like in other programming languages. The getters and setters methods are
often used when:
Example
pg. 13
5.9 Advantages of Encapsulation
• Security: The main advantage of using encapsulation is the security of the data. Encapsulation protects an object
from unauthorized access. It allows private and protected access levels to prevent accidental data modification.
• Data Hiding: The user would not be knowing what is going on behind the scenes. They would only know that to
modify a data member, call the setter method. To read a data member, call the getter method. What these setter and
getter methods are doing is hidden from them.
• Simplicity: It simplifies the maintenance of the application by keeping classes separated and preventing them from
tightly coupling with each other.
• Aesthetics: Bundling data and methods within a class makes code more readable and maintainable.
pg. 14