object-oriented programming in python goldwasser and letscher chapter 6 defining our own classes...

42
Object-Oriented Programming in Python Goldwasser and Letscher Chapter 6 Defining Our Own Classes Terry Scott University of Northern Colorado 2007 Prentice Hall

Post on 18-Dec-2015

227 views

Category:

Documents


2 download

TRANSCRIPT

Object-Oriented Programming in PythonGoldwasser and Letscher

Chapter 6Defining Our Own Classes

Terry ScottUniversity of Northern Colorado

2007 Prentice Hall

2

Introduction: Chapter 6 Topics

• Simple point class.

• Robust point class.

• Television class.

• Fraction class.

• advanced lessons.

3

Predefined versus User Defined Classes

• Why do classes? It supports reuse of code.• Some predefined classes are int, float, list, tuple,

boolean, and file.• By being able to create our own classes we can

configure Python to handle new data types.

4

Point Class

• class Point:• __init__ called the constructor. Executed when a new

object is created from a class.• self lets Python know that a method or data is a

member of the class.– For a data member it should be; self._x where _x

is the class data attribute. Without the self a variable is only a local variable inside a class method.

– For a method the self is the first parameter in the parameter list. __init__(self, . . .)

5

Indentation Pattern for a Class

6

Connection Between a Method (setX) for the object corner and

setX definition in the class.

7

Two Perspectives

• Left: perspective from outside the Point class.

• Right: perspective from inside the Point class.

8

Accessors and Mutators

• Accessors and mutators let users of the class access data member and change data member values.

• getX(self) can return the X data member.

• setX(self, val) will change the X data member to be val.

9

Creating a point class

class Point:

def __init__(self):

self._x = 0

self._y = 0

def getX(self, val):

return self._x

10

Point Class (Continued)

def setX(self, val):self._x = val

def setY(self.val):self._y = val

def setY(self, val):self._y = val

11

Using the Point Class

#create a new object corner of type Point

from SimplePoint import Point

corner = Point()

corner.setX(8) #8 is value of _x in object corner

corner.setY(6) #6 is value of _y in object corner

12

Improved Point class

#if no values are specified for x and y then#the values are set to 0.def __init__(self, initX = 0, initY = 0)

self._x = initXself._y = initY

#Scales the point by a value factor.def scale(self, factor):

self._x *= factorself._y *= factor

13

Improved Point Class (continued)

def distance(self, other):dx = self._x - other._xdy = self._y – other._yreturn sqrt(dx*dx + dy*dy)

#using the distance methodpoint1 = Point(5,20)point2 = Point(45,60) apartAmt = point1.distance(point2)

14

Improved Point Class (continued)

#normalize point – make its distance to the

#origin 1

def normalize(self):

mag = self.distance(Point())

#Point() creates new point at origin

if mag > 0: #don't scale if point is at origin

self.scale(1/mag)

15

Improved Point Class (continued)

#allow print to be able to print a point object.def __str__(self):

return '<'+str(self._x)+', '+str(self._y)+ '>'

#using __str__ methodnew = Point(3, 5)print new#output<3, 5>

16

Improved Point Class (continued)

• Can not use <3,5> to initialize an object. point = <3,5> #this is an error

• Can overload most operators so that they have a new meaning when used with new objects.

• An example is + operator when used with int and float does addition. When used with str it does concatenation (sticks the two strings together).

17

Improved Point Class (continued)

#overloading operators: + overloadingdef __add__(other):

return Point(self._x +other._x, self._y+other._y

#using the __add__ methodnew = Point(3, 5)old = Point(4, 7)total = new + oldprint total#output<7, 12>

18

Polymorphism

• Operator may do a different operation depending on the type that is passed into the operator.

• Multiplication operator: int or float multiply each component by the value, point do a dot product.

• isinstance(variable, Type) returns True if variable is of type Type.

19

Polymorphism

#if val is an int or float it does the if code #if a Point it does the elif code.def __mul__(self, val):

if isinstance(val, (int, float)):#performs regular multiplication operation.return Point(self._x*val, self._y*val)

elif isinstance(val, Point):#performs dot product operation.return self._x*val._x + self._y*val._y

20

Television Class

• Create a user class to emulate the way television controls work.

• General principles– On-off and mute are both toggle switches– All controls only work when the TV is on.– Volume control goes from1 to 10 inclusive.– Channels range from 2 – 99 inclusive. It

wraps around.– Can change channel by entering a channel

number.

21

Television Class

#initializes television objectclass Television:

def __init__(self):self._powerOn = Falseself.muted = Falseself._volume = 5self._channel = 2self._prevChan = 2

22

Television Class Diagram

23

Television Class (continued)

#Clicking flips if on then off and off then on

def togglePower(self):

self._powerOn = not self._powerOn

#Clicking flips between muted and unmuted.

def toggleMute(self):

if self._powerOn:

self._muted = not self._muted

24

Television Class (continued)

#volume can range from 1 upto including 10

def volumeUp(self):

if self._powerOn:

if self._volume < 10:

self._volume += 1

self._muted = False

return self_volume #volume is #displayed on tv when it is changed.

25

Television Class (continued)

#channel increases by one and wraps back to 2def channelUp(self): if self._powerOn:

self._prevChan = self._channelif self._channel == 99: self._channel = 2else: self._channel += 1return self._channel

26

Television Class (continued)

• volumeDown is similar to volumeUp just replace test self._volume < 10 with self._volume > 1 and replace self._volume += 1 with self._volume -= 1

• channelDown is similar to channelUp just replace test self._channel == 99 with self._channel == 2 and replace self._channel += 1 with self._channel -= 1.

27

Television Class (continued)

#Channel is set to number.

def setChannel(self, number):

if self._powerOn:

if 2 <= number <= 99:

self._prevChan = self._channel

self._channel = number

return self._channel

28

Trace of setChannel(7) Tuned to Channel 5 and Was Previously

on Channel 2

29

Television Class (continued)

#Flip to previous channel.

def jumpPrevChannel(self):

if self._powerOn:

incoming = self._channel

self._channel = self._prevChan

self._prevChan = incoming

return self._channel

30

Flawed Swap of Channels

#Left picture is starting situationself._channel = self._prevChanself._prevChan = self._channel#both variables end up at 5

31

One Way to Do This in Python

self._channel, self._prevChan=self.prevChan,self._channel

32

Television Class (continued)

# previous code

#using swap from previous slide

incoming = self._channel

self._channel = self._prevChan

self._prevChan = incoming

# in Python can do the following: can assign

#simultaneously so no need to set to a

#tempory value.

self._channel, self._prevChan=self.prevChan,self._channel

33

Fraction Class

• Fraction consists of two numbers: a numerator and a denominator.

• Must be in lowest terms.• Denominator must be non-negative.• Denominator must be non-zero.• Method types:

– constructor.– arithmetic operators.– comparison operators.– type conversion operators.

34

Fraction Class Code

def __init__(self, numer=0, denom= 0): if denom == 0: self._num = 0 self._den = 0 else: factor = gcd(abs(numer), abs(denom))

if denom < 0: factor = -factor

self._num = numer // factor self._den = denom // factor

35

Fraction Class Code (continued)

#overloads + operator for fraction objects.def __add__(self, other): return Fraction(self._num*other._den +

self._den*other._num, self._den*other._den)

#overload < operator for fraction objects.def __lt__(self, other):

return self._num*other._den<self._den*other._num

36

Fraction Class Code (continued)

# Overloads == operator for fraction objects

def __eq__(self, other):

return self._num == other._num and

self._den == other._den

# Overloads float operator for fraction object

def __float__(self):

return float(self._num) / self._den

37

Fraction Class Code (continued)

# overloads int functiondef __init__(self): return int(float(self))# overload str functiondef __str__(self):

if self._den == 0: return 'undefined'

elif self._den == 1 return str(self._num)

else: return str(self._num) + '/' + str(self._den)

38

Complete Fraction Class

from gcd import gcdclass Fraction: def __init__(self, . . .)

#include constructor code def __add__(self, . . .) #include + operator code def __sub__(self, . . .):

#similar to __add__ code just - instead

39

Complete Fraction Class (continued)

def __mul__(self,other): return Fraction(self._num*other._num, self._den * other._den

def __mul__(self,other): return Fraction(self._num*other._den, self._den * other._num

#include other comparison operators #include float, int, and str conversion operators.

40

Advanced Lessons

#Class-Level Attributes# don't hardwire values such as 0 and 10# volume and 2 and 99 for channelsclass Television:

#class level attributes will be shared by all_minVolume = 0_maxVolume = 10_minChannel = 2_maxChannel = 99

#useTelevision. _minVolume etc instead of hardwired #values that were used before.

41

Advanced Lessons (continued)

# Methods that call other methods

# By using previously defined setChannel method can

# simplify the code.

def channelUp(self):

if self._powerOn:

if self._channel == Television._maxChannel:

goto = Television._minChannel

else:

goto = self._channel + 1

return self.setChannel(goto)

42

Advanced Lessons (continued)

# By separating the wrap-around character-# istics from the actual channel changing the # code is simplified.

# Revised jumpPrevChannel using a # previously defined method. def jumpPrevChannel(self): return self.setChannel(self._prevChan)