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

Lecture 9 - Python Classes and Inheritance

Uploaded by

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

Lecture 9 - Python Classes and Inheritance

Uploaded by

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

ENG 202: Computers and Engineering

Object Oriented Programming in PYTHON


LECTURE 9 – PYTHON Classes and Inheritance

Maurice J. KHABBAZ, Ph.D.


Abstraction of data types
through classes.

Last Time
Basic Coordinate Example.

NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. Friday, December 13, 2019 2
Accessors
(i.e. Getters)

Mutators
(i.e. Setters)
Today More on Classes
Information Hiding
Inheritance
Class Variables

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 3
Class Implementation V.S. Usage
Implementing The Class Using The Class

Implementing a new object type Using the new object type in


with a class: code:
• Define the class. • Create instances of the object
• Define data attributes (i.e. What is?). type.
• Define methods (i.e. How to use?). • Execute operations with them.

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 4
Class Implementation V.S. Usage
Class Definition of an Object Type Instance of a Class

• Class name is the type: • It is one specific realization:


c = Coordinate(1,2)
class Coordinate(object):
• Data attribute values vary between
• Class is defined generically: different instances.
• Use self throughout the class definition: c1 = Coordinate(1, 2)
allows a class instance to refer to itself:
c2 = Coordinate(3, 4)
(self.x – self.y)**2 • c1 and c2 may have different data
• self is a parameter to methods throughout attribute values x and y because they
the class definition. are different objects
• Class defines data and methods common • Any instance has the same structure
across all instances. of the class itself.

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 5
Usage of OOP And
Classes of Objects

• Mimic real life.

• Group objects belonging to the same type

6
Data Attributes:

• Representation of an object with data.


• Abstract descriptions of object characteristics.
Groups of • Examples:
• Point: its x, y and z, coordinates.
Objects Have • Animal: its name, age, type (i.e. cat, dog, horse, … etc).

Attributes: Procedural Attributes (i.e. behavior, operations,


methods):
Recall • Means of interaction with an object.
• Abstract descriptions of the object’s behavior and what it
does.
• Examples:
• Point: find the distance between two points, form a line.
• Animal: eat, drink, make a sound, etc.

NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. Friday, December 13, 2019 7
Class Definition: Recall

class Animal(object):
def __init__(self, age):
self.age = age
self.name = None

myAnimal = Animal(3)

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 8
Accessor and Mutator Methods
• Also known respectively as Getter and Setter methods.
• Should be used outside the class to access (i.e. read/modify) attributes.
• Example:
class Animal(object):
def __init__(self, age):
self.age = age; self.name = None
def getAge(self): return self.age
def getName(self): return self.name
def setAge(self, age): self.age = age
def setName(self, name = “”): self.name = name
def __str__(self): return self.name+“:”+str(self.age)

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 9
An Instance and DOT Notation: Recall
• Instantiation implies the creation of an instance of an object class.
• Example:
a = Animal(3)
• DOT notation used to access attributes (data/methods):
• This is not recommended for accessing data attributes.
• Use ONLY for accessing procedural (methods) attributes:
• Methods will internally handle an instance’s own attributes through the self variable.
• Example: - Access of data attribute
- Allowed but not recommended
a.age
- Access of procedural attributes
a.getAge() - Best use getters and setters
Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 10
Information Hiding
• Class definition authors may change data attribute names:
• Example:
class Animal(object): class Animal(object):
def __init__(self, age): def __init__(self, age):
self.age = age self.years = age
def getAge(self): def getAge(self):
return self.age return self.years

• Direct data attribute access outside the class using DOT ⇒ errors.
• Outside class, use accessor/mutator methods:
• Example: USE a.getAge() NOT a.age
• Good style, easy to maintain code, prevents bugs.
Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 11
Does PYTHON Fail At Information Hiding?
• So far:
• PYTHON allows direct data attribute access from outside class definition.
• Example: print(a.age)

• PYTHON allows direct data attribute mutation from outside class definition.
• Example: a.age = 10

• PYTHON even allows creation of new data attributes from outside class definition.
• Example: a.size = “tiny”
• It is not a good programming style and/or practice.
• How is data encapsulation ensured here? … Well it is, so far, not ensured!
Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 12
Data/Procedural Attributes Access Modifiers
• Data/Procedural attributes in PYTHON are typically:
• Public: accessible from outside the class using the object’s name and DOT.
• Data attributes, in general, have to be made either/or:
• Private: deny any access to them from any environment outside the class.
• Protected: accessible from within the class itself and/or its sub-classes.
• No other external environment is allowed to access such data attributes.
• Enables specific resources of the parent class to be inherited by child class:
• (INHERITANCE DISCUSSED LATER THROUGHOUT THIS LECTURE).
• Ensure data protection/encapsulation through:
• Making data attributes private/protected.
• Keeping procedural attributes public.

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 13
Access Modifiers in PYTHON
• In PYTHON all data/procedural attributes are public by default.
• PYTHON:
• Has no mechanism to effectively restrict access to instance variables/methods.
• Prescribes prefixing convention for variables/methods names with:
• A single underscore “_” to make them protected.
• A double underscore “__” to make them private.
• Example: Original Employee class
class Employee(object):
def __init__(self, name, salary)
self.name = name
self.salary = salary
Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 14
Access Modifiers in PYTHON – Cont’d.
class Employee(object):
def __init__(self, name, salary)
self.name = name
self.salary = salary

• Assume that e = Employee(“Jason”, 1500) is instantiated.


• e’s attributes are accessible and mutable directly:
e.name = “Jad”
e.salary = 2000
print(e.name + “:” + str(e.salary))
• Output: Jad:2000

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 15
Access Modifiers in PYTHON – Cont’d.
class Employee(object): class Employee(object):
def __init__(self, name, salary) def __init__(self, name, salary)
self.name = name self._name = name
self.salary = salary self._salary = salary
protected

• Assume that e = Employee(“Jason”, 1500) is instantiated.


• e’s protected attributes are still accessible and mutable directly:
e._name = “Jad”
e._salary = 2000
print(e._name + “:” + str(e._salary))
• Output: Jad:2000
Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 16
Access Modifiers in PYTHON – Cont’d.
class Employee(object): class Employee(object):
def __init__(self, name, salary) def __init__(self, name, salary)
self.name = name self.__name = name
self.salary = salary self.__salary = salary
private
• Assume that e = Employee(“Jason”, 1500) is instantiated.
• e’s private attributes no longer accessible and mutable directly:
e.__name = “Jad”
Output: AttributeError:
‘Employee’ object has no attribute ‘__name’

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 17
Access Modifiers in PYTHON – Cont’d.
class Employee(object):
def __init__(self, name, salary)
self.__name = name
self.__salary = salary
def getName(self):
Accessor methods
return self.__name
allow indirect access
def getSalary(self):
to private attributes
return self.__salary

• Assume that e = Employee(“Jason”, 1500) is instantiated.


• e’s private attributes no longer accessible and mutable directly:
print(e.getName() + “:” + str(e.getSalary())
Output: Jason:1500
Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 18
Default Arguments
• Defined for formal parameters and used if no actual arguments are passed.
• Example:
def setName(self, name = “”)
self.name = name
a = Animal(3)
a.setName()
print(a.getName()) prints “” to the screen
a.setName(“Piggy”)
print(a.getName()) prints “Piggy” to the screen

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 19
Hierarchies
• Best explained using an example: Accounts

Root
Accounts
Level

Social
Bank E-Mail Parent
Media
Accounts Accounts Level
Accounts

Checking Savings NDU Child


Gmail Hotmail Facebook Whatsapp
Account Account Mail Level

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 20
Hierarchies

• A parent class is also known as a superclass.

• A child class is also known as a subclass:


• Inherits all data and procedural attributes of its parent class.
• Adds more data attributes (information).
• Adds more procedural attributes (methods).
• May override methods of parent classes.

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 21
Inheritance: Parent Class
- Everything is an object
- Class object implements basic PYTHON operations
class Employee(object): (e.g. binding variables, etc)
def __init__(self, name, salary):
self.__name = name; self.__salary = salary
def getName(self): return self.__name
def getSalary(self): return self.__salary
def setName(self, name = “”):
self.__name = name
def setSalary(self, salary = 0):
self.__salary = salary
def __str__(self):
return self.__name + “:” + str(self.__salary)

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 22
Inheritance: Subclass Professor inherits all attributes of Employee:
__init__(), name, salary, getName(), getSalary(),
class Professor(Employee): setName(), setSalary(), __str__()
def teach(self): add new functionality
print(“PYTHON is important because...”)
def __str__(self): Overrides __str__() defined in Employee
return “Dr. ” + self.__name + “:” + str(self.__salary))

• Add new functionality teach():


• Instance of Professor can be called with new methods.
• Instance of Employee yields an error if called with Professor’s new method.
• __init__() is not missing, Professor uses the Employee version.

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 23
Method Usage
• A subclass may have methods with the same name as superclass.

• For an instance of a subclass, look for method in the subclass definition.

• If not found, look for method name up the hierarchy:


• i.e. parent class, grandparent class, and so forth…

• Use the first method up the hierarchy that is found with the called name.

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 24
Inheritance: Example
Parent class is Animal
class Person(Animal):
def __init__(self, name, age):
Animal.__init__(self, age) call Animal constructor
self.setName(name); self.friends = [] Add new data attributes
def getFriends(self): return self.friends
def addFriend(self, frdName):
new methods

if frdNAme not in self.friends:


self.friends.append(frdName)
def speak(self): print(“Hello There!”)
def ageDiff(self, other):
print(abs(self.age – other.age), “years”)
def __str__(self): override Animal’s __str__() method
return “person”: + str(self.name) + “:” + str(self.age)

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 25
Inheritance: Example – Cont’d.
import random bring in methods from random class
class Student(Person): inherits Person and Animal attributes
def __init__(self, name, age, major = None):
Person.__init__(self, name, age)
self.major = major Add new data attributes
def changeMajor(self, major):
self.major = major
def speak(self):
r = random.random() random()method returns a floating point number in [0, 1)
if r < 0.25: print(“I have a homework”)
elif 0.25 <= r < 0.5: print (“I need sleep”)
elif 0.5 <= r < 0.75: print (“I must eat”)
else: print(“I am watching TV”)
def __str__(): return “student:” + self.name + “:” + self.major

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 26
Class Variables and The Rabbit Subclass
• class variables and their values are shared between all instances of a class.
parent class
class Rabbit(Animal):
tag = 1
def __init__(self, age, parent1=None, parent2=None):
Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2
self.rid = Rabbit.tag access class variable
Rabbit.tag += 1 changing the class variable’s value changes
it for all instances that may reference it

• tag used to give unique ID to each new Rabbit instance.

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 27
Rabbit Getter Methods
class Rabbit(Animal):
tag = 1
def __init__(self, age, parent1=None, parent2=None):
Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2
self.rid = Rabbit.tag pads a string with zeros
Rabbit.tag += 1 (e.g. 001 not 1)
def getRID(self): return str(self.rid).zfill(3)
def getParent1(self): return self.parent1
def getParent2(self): return self.parent2
In addition to these specific getters for Rabbit there are
those inherited from Animal: getName() and getAge()
Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 28
Working With Custom-Built Types
def __add__(self, other):
# returning object of same type as this class
return Rabbit(0, self, other)
Recall Rabbit’s __init__(self, age, parent1=None, parent2=None)

• Define the + operator between two Rabbit instances:


• Define what something like this does: r4=r1+r2 (r1/r2 are Rabbit instances)
• r4 is a new Rabbit instance with age 0.
• r4 has self as one parent and other as the other parent.
• In __init__(), parent1 and parent2 are of type Rabbit.

Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 29
Working With Custom-Built Types – Cont’d.
• Decide that two rabbits are equal if they have the same two parents.

def __eq__(self, other):


parentsSame = self.parent1.rid == other.parent1.rid \
and self.parent2.rid == other.parent2.rid
parentsOpposite = self.parent2.rid == other.parent1.rid \
and self.parent1.rid == other.parent2.rid
return parentsSame or parentsOpposite

• Compare IDs of parents since IDs are unique (class variables)


• Note that objects cannot be compared directly:
• Example: self.parent1 == other.parent1 calls __eq__() method.
• The __eq__() call goes over and over until it gets called on None.
• Then it gives an AttributeError when it tries to execute None.parent1
Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 30
Object Oriented Programming
• Create custom-built data collections.

• Organize information.

• Divide and conquer the work.

• Access information in a consistent manner.

• Add layers of complexity.

• Similar to Functions:
• Classes are a mechanism for decomposition and abstraction in programming.
Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 31
Friday, December 13, 2019 NDU - ENG 202 - Maurice J. KHABBAZ, Ph.D. 32

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy