Using Classes Effectively [Andersen, Gries, Lee, Marschner, Van - - PowerPoint PPT Presentation

using classes effectively
SMART_READER_LITE
LIVE PREVIEW

Using Classes Effectively [Andersen, Gries, Lee, Marschner, Van - - PowerPoint PPT Presentation

CS 1110: Introduction to Computing Using Python Lecture 18 Using Classes Effectively [Andersen, Gries, Lee, Marschner, Van Loan, White] Announcements A3 due tonight at 11:59pm. Spring break next week: No office hours No


slide-1
SLIDE 1

Using Classes Effectively

Lecture 18

CS 1110:

Introduction to Computing Using Python

[Andersen, Gries, Lee, Marschner, Van Loan, White]

slide-2
SLIDE 2

Announcements

  • A3 due tonight at 11:59pm.
  • Spring break next week:
  • No office hours
  • No consulting hours
  • Limited piazza

3/30/17 Using Classes Effectively 2

slide-3
SLIDE 3

Making Arguments Optional

  • We can assign default values to

__init__ arguments

  • Write as assignments to

parameters in definition

  • Parameters with default values

are optional

  • Examples:
  • p = Point3() # (0,0,0)
  • p = Point3(1,2,3)

# (1,2,3)

  • p = Point3(1,2) # (1,2,0)
  • p = Point3(y=3) # (0,3,0)
  • p = Point3(1,z=2) # (1,0,2)

class Point3(object): """Instances are points in 3d space x: x coord [float] y: y coord [float] z: z coord [float] """ def __init__(self,x=0,y=0,z=0): """Initializer: makes a new Point Precondition: x,y,z are numbers""" self.x = x self.y = y self.z = z …

3/30/17 3 Using Classes Effectively

slide-4
SLIDE 4

Making Arguments Optional

  • We can assign default values to

__init__ arguments

  • Write as assignments to

parameters in definition

  • Parameters with default values

are optional

  • Examples:
  • p = Point3() # (0,0,0)
  • p = Point3(1,2,3)

# (1,2,3)

  • p = Point3(1,2) # (1,2,0)
  • p = Point3(y=3) # (0,3,0)
  • p = Point3(1,z=2) # (1,0,2)

class Point3(object): """Instances are points in 3d space x: x coord [float] y: y coord [float] z: z coord [float] """ def __init__(self,x=0,y=0,z=0): """Initializer: makes a new Point Precondition: x,y,z are numbers""" self.x = x self.y = y self.z = z …

3/30/17 4

Assigns in order Use parameter name when out of order Can mix two approaches

Using Classes Effectively

slide-5
SLIDE 5

Making Arguments Optional

  • We can assign default values to

__init__ arguments

  • Write as assignments to

parameters in definition

  • Parameters with default values

are optional

  • Examples:
  • p = Point3() # (0,0,0)
  • p = Point3(1,2,3)

# (1,2,3)

  • p = Point3(1,2) # (1,2,0)
  • p = Point3(y=3) # (0,3,0)
  • p = Point3(1,z=2) # (1,0,2)

class Point3(object): """Instances are points in 3d space x: x coord [float] y: y coord [float] z: z coord [float] """ def __init__(self,x=0,y=0,z=0): """Initializer: makes a new Point Precondition: x,y,z are numbers""" self.x = x self.y = y self.z = z …

3/30/17 5

Assigns in order Use parameter name when out of order Can mix two approaches

Using Classes Effectively

slide-6
SLIDE 6

On Tuesday, we learned how to make:

  • Class definitions
  • Class specifications
  • Class variables
  • Methods
  • Attributes (using self)
  • A constructor with __init__

3/30/17 Using Classes Effectively 6

slide-7
SLIDE 7

Today

  • Class definitions
  • Class specifications
  • Class variables
  • Methods
  • Attributes (using self)
  • A constructor with __init__

3/30/17 Using Classes Effectively 7

slide-8
SLIDE 8
  • Type: set of values and the operations on them
  • int: (set: integers; ops: +, –, *, /, …)
  • Time (set: times of day; ops: time span, before/after, …)
  • Rectangle (set: all axis-aligned rectangles in 2D;
  • ps: contains, intersect, …)
  • To define a class, think of a real type you want to make

Designing Types

3/30/17 Using Classes Effectively 8

slide-9
SLIDE 9

Making a Class into a Type

  • 1. Think about what values you want in the set
  • What are the attributes? What values can they have?
  • 2. Think about what operations you want
  • This often influences the previous question
  • To make (1) precise: write a class invariant
  • Statement we promise to keep true after every method call
  • To make (2) precise: write method specifications
  • Statement of what method does/what it expects (preconditions)
  • Write your code to make these statements true!

3/30/17 Using Classes Effectively 9

slide-10
SLIDE 10

Planning out a Class: Time

3/30/17 Using Classes Effectively 10

  • What attributes?
  • What invariants?
  • What methods?
  • What constructor?

(24-hour clock)

slide-11
SLIDE 11

Planning out a Class

class Time(object): """Instances represent times of day. Instance Attributes: hour: hour of day [int in 0..23] min: minute of hour [int in 0..59]""" def __init__(self, hour, min): """The time hour:min. Pre: hour in 0..23; min in 0..59""" def increment(self, hours, mins): """Move this time <hours> hours and <mins> minutes into the future. Pre: hours is int >= 0; mins in 0..59""" def isPM(self): """Returns: this time is noon or later."""

Class Invariant

States what attributes are present and what values they can have. A statement that will always be true of any Time instance.

Method Specification

States what the method does. Gives preconditions stating what is assumed true of the arguments.

3/30/17 Using Classes Effectively 11

slide-12
SLIDE 12

Implementing a Class

  • All that remains is to fill in the methods. (All?!)
  • When implementing methods:
  • 1. Assume preconditions are true
  • 2. Assume class invariant is true to start
  • 3. Ensure method specification is fulfilled
  • 4. Ensure class invariant is true when done
  • Later, when using the class:
  • When calling methods, ensure preconditions are true
  • If attributes are altered, ensure class invariant is true

3/30/17 Using Classes Effectively 14

slide-13
SLIDE 13

Implementing an Initializer

def __init__(self, hour, min): """The time hour:min. Pre: hour in 0..23; min in 0..59"""

You put code here This is true to start This should be true at the end

Instance variables: hour: hour of day [int in 0..23] min: minute of hour [int in 0..59]

3/30/17 Using Classes Effectively 15

slide-14
SLIDE 14

Implementing an Initializer

def __init__(self, hour, min): """The time hour:min. Pre: hour in 0..23; min in 0..59"""

This is true to start This should be true at the end

Instance variables: hour: hour of day [int in 0..23] min: minute of hour [int in 0..59]

3/30/17 Using Classes Effectively 16

A: Time.hour = hour Time.min = min B: hour = hour min = min C: self.hour = hour self.min = min D: self.hour = Time.hour self.min = Time.min

slide-15
SLIDE 15

Instance variables: hour: hour of day [int in 0..23] min: minute of hour [int in 0..59]

Implementing a Method

def increment(self, hours, mins): """Move this time <hours> hours and <mins> minutes into the future. Pre: hours [int] >= 0; mins in 0..59"""

You put code here This is also true to start This should be true at the end

self.min = self.min + mins self.hour = self.hour + hours

This is true to start What we are supposed to accomplish

Instance variables: hour: hour of day [int in 0..23] min: minute of hour [int in 0..59]

?

3/30/17 Using Classes Effectively 17

slide-16
SLIDE 16

Instance variables: hour: hour of day [int in 0..23] min: minute of hour [int in 0..59]

Implementing a Method

def increment(self, hours, mins): """Move this time <hours> hours and <mins> minutes into the future. Pre: hours [int] >= 0; mins in 0..59"""

You put code here This is also true to start This should be true at the end

self.min = self.min + mins self.hour = (self.hour + hours + self.min / 60) self.min = self.min % 60 self.hour = self.hour % 24

This is true to start What we are supposed to accomplish

Instance variables: hour: hour of day [int in 0..23] min: minute of hour [int in 0..59]

3/30/17 Using Classes Effectively 18

slide-17
SLIDE 17

Example: class Time

3/30/17 Using Classes Effectively 19

slide-18
SLIDE 18

Special Methods in Python

  • __init__ for initializer
  • __str__ for str()
  • __repr__ for backquotes
  • Start/end with 2 underscores
  • This is standard in Python
  • Used in all special methods
  • Also for special attributes
  • For a complete list, see

http://docs.python.org/refere nce/datamodel.html

class Point3(object): """Instances are points in 3D space""" … def __init__(self,x=0,y=0,z=0): """Initializer: makes new Point3""" … def __str__(self,q): """Returns: string with contents""" … def __repr__(self,q): """Returns: unambiguous string""" …

3/30/17 Using Classes Effectively 20

slide-19
SLIDE 19

Example: Converting Values to Strings

str() Function

  • Usage: str(<expression>)
  • Evaluates the expression
  • Converts it into a string
  • How does it convert?
  • str(2) → '2'
  • str(True) → 'True'
  • str('True') → 'True'
  • str(Point3()) →

'(0.0,0.0,0.0)'

Backquotes

  • Usage: `<expression>`
  • Evaluates the expression
  • Converts it into a string
  • How does it convert?
  • `2` → '2'
  • `True` → 'True'
  • `'True'` → "'True'"
  • `Point3()` →

"<class 'Point3'> (0.0,0.0,0.0)"

3/30/17 Using Classes Effectively 21

slide-20
SLIDE 20

Example: Converting Values to Strings

str() Function

  • Usage: str(<expression>)
  • Evaluates the expression
  • Converts it into a string
  • How does it convert?
  • str(2) → '2'
  • str(True) → 'True'
  • str('True') → 'True'
  • str(Point3()) →

'(0.0,0.0,0.0)'

Backquotes

  • Usage: `<expression>`
  • Evaluates the expression
  • Converts it into a string
  • How does it convert?
  • `2` → '2'
  • `True` → 'True'
  • `'True'` → "'True'"
  • `Point3()` →

"<class 'Point3'> (0.0,0.0,0.0)"

3/30/17 Using Classes Effectively 22

What type is this value? The value’s type is clear

Backquotes are for unambigious representation

slide-21
SLIDE 21

What Does str() Do On Objects?

  • Does NOT display contents

>>> p = Point3(1,2,3) >>> str(p) '<Point3 object at 0x1007a90>'

  • Must add a special method
  • __str__ for str()
  • __repr__ for backquotes
  • Could get away with just one
  • Backquotes require __repr__
  • str() can use __repr__

(if __str__ is not there)

class Point3(object): """Instances are points in 3d space""" … def __str__(self): """Returns: string with contents""" return '('+self.x + ',' + self.y + ',' + self.z + ')' def __repr__(self): """Returns: unambiguous string""" return str(self.__class__)+ str(self) Gives the class name

3/30/17 Using Classes Effectively 23

__repr__ using __str__ as helper

slide-22
SLIDE 22

Planning out a Class: Fraction

3/30/17 Using Classes Effectively 24

slide-23
SLIDE 23
slide-24
SLIDE 24

Planning out a Class: Fraction

  • What attributes?
  • What invariants?
  • What methods?
  • What constructor?

class Fraction(object): """Instance is a fraction n/d Attributes: numerator: top [int] denominator: bottom [int > 0] """ def __init__(self,n=0,d=1): """Init: makes a Fraction""" self.numerator = n self.denominator = d

3/30/17 Using Classes Effectively 26

slide-25
SLIDE 25

Example: class Fraction

3/30/17 Using Classes Effectively 27

slide-26
SLIDE 26

Problem: Doing Math is Unwieldy

What We Want

1 2 + 1 3 + 1 4 ∗ 5 4

What We Get >>> p = Fraction(1,2) >>> q = Fraction(1,3) >>> r = Fraction(1,4) >>> s = Fraction(5,4) >>> (p.add(q.add(r))).mult(s)

3/30/17 Using Classes Effectively 28

Pain!

Why not use the standard Python math operations?

slide-27
SLIDE 27

Operator Overloading: Addition

class Fraction(object): """Instance attributes: numerator: top [int] denominator: bottom [int > 0]""” def __add__(self,q): """Returns: Sum of self, q Makes a new Fraction Precondition: q a Fraction""" assert type(q) == Fraction bot = self.denominator*q.denominator top = (self.numerator*q.denominator+ self.denominator*q.numerator) return Fraction(top,bot)

>>> p = Fraction(1,2) >>> q = Fraction(3,4) >>> r = p+q >>> r = p.__add__(q)

Python converts to

Operator overloading uses method in object on left.

3/30/17 Using Classes Effectively 29

slide-28
SLIDE 28

Operator Overloading: Multiplication

class Fraction(object): """Instance attributes: numerator: top [int] denominator: bottom [int > 0]""” def __mul__(self,q): """Returns: Product of self, q Makes a new Fraction; does not modify contents of self or q Precondition: q a Fraction""" assert type(q) == Fraction top = self.numerator*q.numerator bot = self.denominator*q.denominator return Fraction(top,bot)

>>> p = Fraction(1,2) >>> q = Fraction(3,4) >>> r = p*q >>> r = p.__mul__(q)

Python converts to

Operator overloading uses method in object on left.

3/30/17 Using Classes Effectively 30

slide-29
SLIDE 29

Data Encapsulation

class Fraction(object): """Instance attributes: _numerator: top [int] _denominator: bottom [int > 0]""" def getDenominator(self): """Returns: numerator attribute""" return self._denominator def setDenominator(self, d): """Alters denomenator to be d Pre: d is an int > 0""" assert type(d) == int assert 0 < d self._denominator = d

Getter Setter

Precondition is same as attribute invariant. Naming Convention The underscore means “should not access the attribute directly.”

3/30/17 Using Classes Effectively 32

slide-30
SLIDE 30

Enforcing Invariants

class Fraction(object): """Instance attributes: numerator: top [int] denominator: bottom [int > 0] """

  • These are just comments!
  • Do not enforce anything.
  • Idea: Restrict direct access
  • Only access via methods
  • Use asserts to enforce them
  • Examples:

def getNumerator(self): """Returns: numerator""" return self.numerator def setNumerator(self,value): """Sets numerator to value""" assert type(value) == int self.numerator = value

3/30/17 Using Classes Effectively 33

Invariants: Properties that are always true.