Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
9 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)
9 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