0% found this document useful (0 votes)
2 views

6. OOP

The document provides an overview of Object-Oriented Programming (OOP) principles, including concepts such as classes, attributes, methods, inheritance, and polymorphism. It contrasts OOP with procedural programming, highlighting the advantages of OOP in terms of clarity, organization, and data integrity. Additionally, it discusses the use of properties to control attribute access and the importance of encapsulation and abstraction in class design.

Uploaded by

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

6. OOP

The document provides an overview of Object-Oriented Programming (OOP) principles, including concepts such as classes, attributes, methods, inheritance, and polymorphism. It contrasts OOP with procedural programming, highlighting the advantages of OOP in terms of clarity, organization, and data integrity. Additionally, it discusses the use of properties to control attribute access and the importance of encapsulation and abstraction in class design.

Uploaded by

stalinking2006
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 41

OBJECT-ORIENTED

PROGRAMMING

By
Prof. G V S SARMA
Department of Chemical Engineering
Andhra University College of Engineering(A)
Andhra University
CONTENTS

 The Object-Oriented Approach


 Object-Oriented Concepts and Terminology
 Custom Classes
 Attributes and Methods
 Inheritance and Polymorphism
 Using Properties to Control Attribute Access
THE OBJECT-ORIENTED APPROACH
 Object-oriented programming is a programming paradigm
based on the concept of 'objects,' which can contain data and
code.

In OOP, code is organized into classes, which act as blueprints for


creating objects.
 Procedural programming focuses on writing procedures or
routines to perform tasks.

It follows a linear flow of execution and is often used for tasks that
can be broken down into a series of steps.
Drawbacks of Procedural Programming:
1. Ambiguity and Lack of Clarity:
 In procedural programming, representing circles using 3-tuples can be
ambiguous.
 It's unclear what each element of the tuple represents (e.g., (x, y, radius)
or (radius, x, y)).
Example: circle = (11, 60, 8)

2. Difficulty in Accessing Data:


 Accessing circle properties by index position only can lead to confusion
and errors.
 Functions expecting specific circle data require tuple unpacking, which
adds complexity.
Example: distance = distance_from_origin(*circle[:2])
3. Lack of Data Validation:
 Procedural programming lacks built-in mechanisms for validating
circle data.
 Invalid circles (e.g., negative radius) can be created without raising
exceptions.

Example: circle = (33, 56, -5)

4. Limited Mutability and Safety:


 Modifying circle properties (e.g., coordinates, radius) may require
cumbersome methods like tuple unpacking or direct manipulation.
 There's no inherent protection against setting invalid circle data.

Example: circle = circle._replace(radius=12)


5. Alternative Approaches Bring Additional Issues:
 Using mutable data types like lists or dictionaries for circles adds
convenience but sacrifices data validation and safety.
 Lists or dictionaries lack built-in validation for circle properties and
may allow inappropriate method calls.
Example: circle = [36, 77, 8]

 Adopting object-oriented programming principles to the above example


can provide a clearer, more organized, and safer way to represent
circles, ensuring data integrity and facilitating easier maintenance and
extension of code
OBJECT-ORIENTED CONCEPTS AND
TERMINOLOGY
Terminology Clarification:
 Class: A class is a blueprint for creating objects. It defines the
properties (attributes) and behaviors (methods) that objects of the
class will have.
 Type: In Python, a type refers to the category of an object. Every
object belongs to a specific type, which determines its behavior and
the operations that can be performed on it.
 Data Type: A data type specifies the type of data that can be stored
and manipulated in a programming language. In Python, both built-in
and custom classes can serve as data types.
Encapsulation in Classes:

Encapsulation is the bundling of data (attributes) and methods


(functions) that operate on that data within a single unit, i.e., a class. It
allows for the abstraction of data and behavior.

Example: The ‘str’ class encapsulates a string of characters and provides


methods like upper() to manipulate that string.

Abstraction:
• Abstraction involves hiding the complex implementation details of a
system while exposing only the relevant features or behaviors.
• It allows developers to focus on essential aspects of an object or system
and ignore unnecessary complexities.
Special Methods:

Special methods in Python are predefined methods with names that


begin and end with double underscores. They enable built-in
operations to be performed on objects, such as addition, subtraction, and
string representation.

Example: The _ _add_ _() special method allows objects to support the +
operator for addition.

Attributes and Methods:

Attributes: Attributes are pieces of data associated with an object. They


represent the state of the object. Attributes can be data attributes (e.g.,
‘real’ and ‘imag’ in a complex number) or methods (functions) that operate
on the object's data.

Methods: Methods are functions defined within a class that operate on the
Properties:

Properties in Python are special attributes that are accessed like


instance variables but are managed by methods. They allow for
controlled access to data and enable validation and manipulation behind the
scenes.

Example: A property can be used to validate and manipulate the radius of


a circle to ensure it is always positive.

Variable Scope:

Variable scope determines where in the code a variable is accessible.

In Python, variables can have different scopes, including local scope


(within a function), global scope (across the entire module), and instance
scope (specific to an object).
Namespace:
• A namespace is a mapping from names to objects.
• It provides a way to avoid name conflicts by organizing the names
of variables, functions, and classes into distinct groups.

Inheritance:
• Inheritance is the mechanism by which a new class (subclass) can
inherit attributes and methods from an existing class (base class
or superclass).
• It allows for code reuse and the extension of existing functionality.
Base Class (Superclass):

The base class is the class from which other classes inherit. It provides the
foundation for the inheritance hierarchy.

Subclass (Derived Class):

The subclass is a class that inherits attributes and methods from a base
class. It can extend or modify the functionality of the base class.

Naming Conventions:
• In Python, naming conventions help maintain consistency and
readability in code.
• Custom classes follow the convention of using an uppercase letter as
the first letter of the class name.
CUSTOM CLASSES
 Custom classes can be created using the ‘class’ keyword, which allows
developers to define their own data types with specific attributes and
methods.

Simple Class Definition:


class ClassName:
# Class suite (optional)
pass

Class with Inheritance:


class ClassName(BaseClass1, BaseClass2, ...):
# Class suite (optional)
pass
Class Statement:

The ‘class’ keyword is used to declare a new class. This statement is


followed by the name of the class being defined.

Class Suite:

The suite of the class consists of attributes, methods, and other


statements that define the behavior and properties of the class.
This suite is indented under the class statement.

Inheritance:

A class can inherit attributes and methods from one or more base
classes by specifying them inside parentheses after the class name. This
allows for code reuse and promotes modular design.
Dynamic Class Creation:

Similar to function definitions (‘def’ statements), class definitions (class


statements) are executable statements in Python. This means that
classes can be created dynamically during runtime if needed.

Class Methods:

Methods (functions) within a class are defined using ‘def’ statements


inside the class suite. These methods can operate on the object's data
(attributes) and perform specific actions.

Class Instances:

Instances of a class (objects) are created by calling the class with any
required arguments. This invokes the class's constructor method
(__init__), which initializes the object's state.
Example:
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year

def drive(self):
print(f"{self.make} {self.model} is driving.")

# Creating instances of the Car class


car1 = Car("Toyota", "Camry", 2020)
car2 = Car("Honda", "Accord", 2019)

# Invoking methods on objects


car1.drive() # Output: Toyota Camry is driving.
car2.drive() # Output: Honda Accord is driving.
• In the above example, Car is a custom class with attributes (make,
model, year) and a method (drive).

• Instances of the Car class are created using the constructor method
(__init__) by passing arguments, and methods are invoked on these
objects to perform specific actions.

Constructor Method (__init__):

The __init__ method is a special method used to initialize new


instances of the class. It is called automatically when a new object is
created.

Instance Attributes:

Instance attributes are unique to each object and are initialized within
the __init__ method using the ‘self’ keyword.
ATTRIBUTES AND METHODS
Attributes:

Attributes, also known as fields, properties, or member variables, represent


the data elements that characterize objects.

There are two main types of attributes in OOP:

1. Instance Attributes: These attributes are specific to each object instance


of a class. They are defined within the class but outside any method and
accessed using the ‘self’ keyword within methods.

2. Class Attributes: Class attributes are shared among all instances of a


class. They are defined within the class but outside any method and
accessed using the class name. Class attributes define properties that are
common to all objects of the class.
Methods:

Methods, also referred to as member functions, are functions defined


within a class that define the behavior of objects.

There are several types of methods in OOP:

1. Instance Methods: Instance methods operate on individual instances of


a class. They have access to instance attributes and are defined with the
‘self’ parameter as the first parameter.

2. Class Methods: Class methods operate on the class itself rather than
individual instances. They have access to class attributes but not to
instance attributes. They are defined using the ‘@classmethod’
decorator and have a ‘cls’ parameter as the first parameter.
3. Static Methods: Static methods are independent of class and instance
attributes. They are defined using the ‘@staticmethod’ decorator and
do not have access to ‘self’ or ‘cls’ parameters. Static methods are
primarily used for utility functions that do not require access to instance
or class attributes.

Example:

Simple class, Point, that holds an (x, y) coordinate. The class is defined
in a file named Shape.py

Code continues in the next slide……


Code:

import math def __repr__(self):

class Point: return “Point({0.x!r}, {0.y!r})”

def __init__(self, x=0, y=0): def __str__(self):

self.x = x return “({0.x!r}, {0.y!r})"

self.y = y

def distance_from_origin(self):

return math.hypot(self.x, self.y)

def __eq__(self, other):

return self.x == other.x and self.y ==


other.y
Explanation:
 Class Definition: The ‘Point’ class represents a point in 2D space and
encapsulates its (x, y) coordinates along with methods to perform
operations on points.
 Constructor (__init__): The ‘__init__’ method initializes a ‘Point’ object
with optional x and y coordinates. If no coordinates are provided, the
default values are set to (0, 0).
 Instance Method (distance_from_origin): This method calculates the
distance of the point from the origin (0, 0) using the Pythagorean theorem
(math.hypot). It returns the distance as a floating-point number.
 Special Method (__eq__): The __eq__ method overrides the equality
operator (==) to compare two Point objects based on their x and y
coordinates. It returns ‘True’ if the coordinates are equal, ‘False’
otherwise.
 Special Method (__repr__): The __repr__ method returns a string
representation of the Point object that can be evaluated using ‘eval()’ to
recreate the object. It provides a formal representation of the object's
state.
 Special Method (__str__): The __str__ method returns a string
representation of the Point object intended for human-readable output. It
provides a more user-friendly representation compared to __repr__.
Usage:
import Shape

# Create Point objects


a = Shape.Point()
b = Shape.Point(3, 4)

# Access attributes and call methods


print(repr(a)) # Output: Point(0, 0)
print(str(b)) # Output: (3, 4)
print(b.distance_from_origin()) # Output: 5.0
print(b.x) # Output: 3
print(a == b) # Output: False
INHERITANCE AND POLYMORPHISM

Inheritance

• Inheritance is a fundamental concept in object-oriented programming that


allows a new class to inherit the properties and behaviors
(attributes and methods) of an existing class.

• The class being inherited from is called the base class or superclass,
and the class inheriting from it is called the derived class or subclass.

• When a subclass inherits from a superclass, it gains access to all the


attributes and methods of the superclass. This allows for code reuse and
promotes a hierarchical organization of classes
• The subclass can also extend or override the functionality of the superclass
by adding new attributes or methods, or by modifying existing ones.

• In Python, inheritance is achieved by specifying the name of the base


class(es) in parentheses after the name of the subclass when defining the
subclass.

Example:

class Superclass:

# Superclass definition

class Subclass(Superclass):

# Subclass definition
Polymorphism
• Polymorphism is the ability of different objects to respond to the
same message (method call) in different ways.

• It allows objects of different classes to be treated interchangeably if they


support a common interface (i.e., have methods with the same name and
parameters).

• Polymorphism is achieved through dynamic typing and duck typing.

• Dynamic typing means that the type of an object is determined at


runtime, allowing objects of different types to be used interchangeably.

• Duck typing is a concept that focuses on an object's behavior rather


than its type.
Example:

class Circle(Point):
def __init__(self, radius, x=0, y=0):
super().__init__(x, y)
self.radius = radius
def edge_distance_from_origin(self):
return abs(self.distance_from_origin() self.radius)
def area(self):
return math.pi * (self.radius ** 2)
def circumference(self):
return 2 * math.pi * self.radius
def __eq__(self, other):
return self.radius == other.radius and super().__eq__(other)
def __repr__(self):
return "Circle({0.radius!r},{0.x!r},{0.y!r})".format(self)
def __str__(self):
return repr(self)

p = Shape.Point(28, 45)

c = Shape.Circle(5, 28, 45)

print(p.distance_from_origin()) # Output: 53.0

print(c.distance_from_origin()) # Output: 53.0


From the example,
 The Circle class inherits from the Point class using the syntax class
Circle(Point). This means that Circle inherits all attributes and methods defined
in the Point class.
 By inheriting from the Point class, the Circle class automatically gains access to
attributes and methods such as x, y, distance_from_origin(), __eq__(),
__repr__(), and __str__().
 Polymorphism is demonstrated by the distance_from_origin() method.
This method is defined in the Point class, but it can be called on both Point
and Circle objects interchangeably.
 Despite distance_from_origin() being originally defined in the Point class, it is
also applicable to Circle objects because they inherit this method from the Point
class.
 Inheritance allows the Circle class to inherit attributes and
methods from the Point class, while polymorphism enables objects
of different types (Point and Circle) to respond to the same method
call (distance_from_origin()) in different ways, demonstrating the
flexibility and reusability of object-oriented programming principles in
Python.
USING PROPERTIES TO CONTROL
ATTRIBUTE ACCESS
 In object-oriented programming, properties are a powerful way to
control attribute access and provide validation, computation, or
customization of attribute behavior.

Getter Methods:
 Properties are defined using getter methods, which are decorated with
@property.
 A getter method retrieves the value of an attribute.
 Getter methods allow accessing the value of an attribute in a read-only
manner.
Property Decorator:
 The @property decorator is used to define getter methods, making
them accessible as properties.
 It provides a concise and clear syntax for defining properties in Python
classes.

Setter Methods:
 Properties can also have setter methods, allowing for validation or
modification of attribute values when they are set.
 Setter methods are decorated with @<property_name>.setter.
 A setter method assigns a new value to an attribute.
Private Attributes:
 Properties can be used to access private attributes (attributes prefixed
with double underscores __).
 Private attributes are conventionally used to store attribute values
while providing controlled access through properties.

Validation:
 Properties can enforce validation rules to ensure that attribute values
meet specific criteria.
Docstrings and Doctests:
 Properties can include docstrings and doctests to provide
documentation and test cases for attribute access.
 Docstrings describe the purpose and usage of properties, while
doctests provide executable examples to verify property behavior.

Initializer:
 Properties can be initialized within the class initializer (__init__
method) to ensure proper attribute setup during object creation.
Example:

class Circle(Point):

def __init__(self, radius, x=0, y=0):

self.radius = radius

@property

def area(self):
"""Calculate the area of the circle."""

return math.pi * (self.radius ** 2)

@property

def edge_distance_from_origin(self):

"""Calculate the distance from the edge of the circle to the origin."""

return abs(self.distance_from_origin() self.radius)


@property

def radius(self):

"""The radius of the circle."""

return self.__radius

@radius.setter

def radius(self, radius):

"""Set the radius of the circle."""

assert radius > 0, "radius must be nonzero and non-negative"

self.__radius = radius

def distance_from_origin(self):

"""Calculate the distance from the center of the circle to the origin."""

return 0 # Assuming this method is implemented elsewhere


def __repr__(self):

return f"Circle(radius={self.radius})"

circle = Circle(5)

print(circle.radius) # Output: 5

print(circle.area) # Output: 78.53981633974483

print(circle.edge_distance_from_origin) # Output: 5.0


Explanation:

Class Definition:
 The Circle class is defined with methods for calculating the area,
edge distance from the origin, and accessing/modifying the radius
attribute.

Properties:
 Properties like area, edge_distance_from_origin, and radius are
defined using the @property decorator.
 The area and edge_distance_from_origin properties provide computed
values based on the radius.
 The radius property encapsulates access to the __radius private
attribute and includes a setter method for validation.
Getter and Setter Methods:
 Getter and setter methods are defined using the @property and
@<property_name>.setter decorators, respectively.
 The radius property includes getter and setter methods for accessing
and modifying the radius attribute.

Validation:
 The setter method for the radius property includes validation to
ensure that the radius value is non-zero and non-negative.
THANK YOU

You might also like