You are on page 1of 30

Lecture 18

Classes and Types


Recall: Overloading Multiplication
class Fraction(object): >>> p = Fraction(1,2)
numerator = 0 # int
denominator = 1 # int >
>>> q = Fraction(3,4)
0 >>> r = p*q

Python
def mul (self,q): converts to
"""Returns: Product of self,
q
Makes a new Fraction; does not >>> r = p. mul (q)
modify contents of self or q
Precondition: q a Fraction"""
Operator overloading uses
assert type(q) == Fraction
method in object on left.
top =
self.numerator*q.numerator
bot =
Classes and Types 2
self.denominator*q.denominat
or
Recall: Overloading Multiplication
class Fraction(object): >>> p = Fraction(1,2)
numerator = 0 # int
denominator = 1 # int >
>>> q = 2 # an int
0 >>> r = p*q

Python
def mul (self,q): converts to
"""Returns: Product of self,
q
Makes a new Fraction; does not >>> r = p. mul (q) #
modify contents of self or q ERROR
Precondition: q a Fraction"""
assert type(q) == Fraction
Can only multiply fractions.
top =
self.numerator*q.numerator But ints “make sense” too.
bot =
Classes and Types 3
self.denominator*q.denominat
or
Dispatch on Type
• Types determine behavior class Fraction(object):

■ Diff types = diff behavior
def mul (self,q):
■ Example: + (plus) """Returns: Product of self,
• Addition for numbers q
• Concatenation for strings Precondition: q a Fraction or
int"""
• Can implement with ifs if type(q) == Fraction:
■ Main method checks type return self._mulFrac(q)
■ “Dispatches” to right helper elif type(q) == int:
return self._mulInt(q)
• How all operators work …
■ Checks (class) type on left def _mulInt(self,q): # Hidden
■ Dispatches to that method method
return Fraction(self.numerator*q,
Classes and Types self.denominator) 4
Dispatch on Type
• Types determine behavior class Fraction(object):

■ Diff types = diff behavior
def mul (self,q):
■ Example: + (plus) """Returns: Product of self,
• Addition for numbers q
• Concatenation for strings Precondition: q a Fraction or
int"""
• Can implement with ifs if type(q) == Fraction:
■ Main method checks type
Classreetsuranrseelfm._maiu
nlFrwaca(qy) to handle
■ “Dispatches” to right helper …
“deliisf ptyaptec(qh)
• How all operators work
=o=nintty: pe” in
■ Checks (class) type on left
Python.
■ Dispatches to that method
Othreeturrlnasnelgf.u_maugl
10/25/12 Classes and Types eInst(hq)ave other 5
Classes and Types: A Problem
class Employee(object): >>> # Promote Bob to
"""An Employee with a salary""" executive

>>> e = Employee('Bob',2011)
def eq (self,other):
if (not type(other) == >>> f = Executive('Bob',2011)
Employee): return False >>> e == f
return (self.name == other.name False
and
self.start == other.start and
self.salary == other.salary) Exactly the same contents.
Only difference is the type.
class Executive(Employee):
"""An Employee with a bonus.""" Do we want it like this?

Classes and Types 6
The isinstance Function
• isinstance(<obj>,<class>) 5298179176
■ True if <obj> has a <class>
Employee
partition in its folder nam 'Fred'
■ False otherwise e
start 2012 salar 0.0
• Example: y
■ isinstance(e,Executive) is init str ()
True (…)
■ isinstance(e,Employee) is …
Executive
True bonus
■ isinstance(e,object) is True 0.0

■ isinstance(e,str) is False str ()


init
• Generally preferable to type (…)
■ Plays better with super Classes and Types … 7

■ If not sure, use isinstance


The isinstance Function
class Employee(object):
• isinstance(<obj>,<class>) …
■ True if <obj> has a <class> def eq (self,other):
partition in its folder if (not
■ False otherwise isinstance(other,Employee)):
return False
• Example: return (self.name == other.name
■ isinstance(e,Executive) is and self.start == other.start
True and self.salary ==
other.salary)
■ isinstance(e,Employee) is
True class Executive(Employee):
■ isinstance(e,object) is True …
def eq (self,other):
■ isinstance(e,str) is False
result = super(Executive,self). eq
• Generally preferable to (other) if (isinstance(other,Executive)):
return result and self.bonus = other.bonus
type Classes and Types 10
return result
■ Plays better with super
The isinstance Function
class Employee(object):
• isinstance(<obj>,<class>) …
■ True if <obj> has a <class> def eq (self,other):
partition in its folder if (not
■ False otherwise isinstance(other,Employee)):
return False
• Example: return (self.name == other.name
■ isinstance(e,Executive) is and self.start == other.start
True and self.salary ==
other.salary)
■ isinstance(e,Employee) is
True class Executive(Employee):
■ isinstance(e,object) is True …
def eq (self,other):
■ isinstance(e,str) is False
result = super(Executive,self). eq
• Generally preferable to (other) if (isinstance(other,Executive)):
return result and self.bonus = other.bonus
type
10/25/12 Classes and Types 9
return result
■ Plays better with super
isinstance and Subclasses
>>> e =
Employee('Bob',2011)
>>> isinstance(e,Executive) 4298768184
??? Employee

A: True name 'Bob'

B: False start 2011 salary 50k


C: Error
init (…) str ()
D: I …
don’t
know

Classes and Types 10


isinstance and Subclasses
>>> e = objec
Employee('Bob',2011) t
>>> isinstance(e,Executive)
??? Employe
e
A: True
B: False Correct Executiv
C: Error e
D: I don’t know → means “extends”
or “is an instance of”

Classes and Types 11


Error Types in Python
def foo(): def
assert 1 == 2, 'My foo():
x=5/0
error' …

>>> foo()
>>> foo() ZeroDivisionError:
AssertionError: My integer division or
error Class Names modulo by zero

Classes and Types 12


Error Types in Python
def foo(): def
Information about an error
assert 1 == 2, 'My foo():
ixs s=to5re/d i0nside an
error'
… object. T…he error type
is the class of the error
object.
>>> foo()
>>> foo()
AssertionError: My
ZeroDivisionError:
error Class Names
integer division or
modulo by zero
10/25/12 Classes and Types 13
Error Types in Python
• All errors are instances of class BaseException
456789
• This allows us to organize them in a hierarchy
BaseException BaseExceptio
'My error' n

init (msg='') str ()



Exception → means “extends”
Exception or “is an instance of”
StandardError
StandardError

AssertionError AssertionError

Classes and Types 14


Python Error Type Hierarchy
Exception
Argument has Argument has
wrong type wrong value
SystemExit StandardError (e.g. (e.g.
float([1])) float('a'))

AssertionError AttributeError ArithmeticError IOError TypeError ValueError


ZeroDivisionError OverflowError …

Why so many error types?

Classes and Types 15


Recall: Recovering from Errors
• try-except blocks allow us to recover from errors
■ Do the code that is in the try-block
■ Once an error occurs, jump to the catch
• Example:
try:
might have an error
input = raw_input() # get number from
user x = float(input) # convert string to
print 'The next number is
float
'+str(x+1) except:
executes if have an error
print 'Hey! That is not a
number!'
Classes and Types 16
Errors and Dispatch on Type
• try-except blocks can be restricted to specific errors
■ Doe except if error is an instance of that type
■ If error not an instance, do not recover
• Example:
try May have IOError

: input = raw_input() # get number from


user x = float(input) # convert string
to float print 'The next number is May have ValueError
'+str(x+1)
except Only recovers ValueError.
ValueError:
print 'Hey! That is not a Other errors ignored.

number!'
Classes and Types 17
Errors and Dispatch on Type
• try-except blocks can be restricted to specific errors
■ Doe except if error is an instance of that type
■ If error not an instance, do not recover
• Example:
try May have IOError

: input = raw_input() # get number from


user x = float(input) # convert string
to float print 'The next number is May have ValueError
'+str(x+1)
except Only recovers IOError.
IOError:
print 'Check your Other errors ignored.

keyboard!'
Classes and Types 18
Creating Errors in Python
• Create errors with raise def foo(x):
■ Usage: raise <exp> assert x < 2, 'My error'
■ exp evaluates to an object …
■ An instance of Exception Identical
• Tailor your error types
def
■ ValueError: Bad value
■ TypeError: Bad type
foo(x):
• Still prefer asserts for if x >=
preconditions, however 2:
■ Compact and easy to …m=
read 'My
Classes and Types
error' 19
Raising and Try-Except
def • The value of
foo(): foo()?
x=0 A: 0
try: B: 2
raise StandardError() x C: 3
D: No value. It
=2
stops! E: I don’t know
except
StandardError: x =
3
return x
Classes and Types 20
Raising and Try-Except
def • The value of
foo(): foo()?
x=0 A: 0
try: B: 2
raise StandardError() x C: 3 Correct
D: No value. It
=2
stops! E: I
except don’t know
StandardError: x =
3
return x
Classes and Types 21
Raising and Try-Except
def • The value of
foo(): foo()?
x=0 A: 0
try: B: 2
raise StandardError() x C: 3
D: No value. It
=2
stops! E: I don’t know
except
Exception: x =
3
return x
Classes and Types 22
Raising and Try-Except
def • The value of
foo(): foo()?
x=0 A: 0
try: B: 2
raise StandardError() x C: 3 Correct
D: No value. It
=2
stops! E: I
except don’t know
Exception: x =
3
return x
Classes and Types 23
Raising and Try-Except
def • The value of
foo(): foo()?
x=0 A: 0
try: B: 2
raise StandardError() x C: 3
D: No value. It
=2
stops! E: I don’t know
except
AssertionError: x =
3
return x
Classes and Types 24
Raising and Try-Except
def • The value of
foo(): foo()?
x=0 A: 0
try: B: 2
raise StandardError() x C: 3
D: No value. It stops!
=2
Correct E: I don’t
except know
AssertionError: x = Python uses isinstance
3 to match Error types
return x
Classes and Types 25
Creating Your Own Exceptions
class
CustomError(StandardError):
"""An instance is a custom
exception""" pass Only issues is choice of
parent Exception class.
This is all you need Use StandardError if
you are unsure what.
■ No extra fields
■ No extra methods
■ No constructors
Inherit everything

Classes and Types 26


Errors and Dispatch on Type
• try-except can put the error in a variable
• Example:
try:
input = raw_input() # get number from
user x = float(input) # convert string
to float print 'The next number is
'+str(x+1)
except ValueError as Some Error subclasses
e: print e.message have more attributes
print 'Hey! That is not a
number!'

Classes and Types 27


Typing Philosophy in Python
• Duck Typing: class Employee(object):
■ “Type” object is determined """An Employee with a salary"”"
by its methods and properties …
■ Not the same as type() value def eq (self,other):
■ Preferred by Python experts if (not (hasattr(other,'name')
• Implement with hasattr() and hasattr(other,'start')
and
■ hasattr(<object>,<string>)
hasattr(other,'salary'))
■ Returns true if object has an
return False
attribute/method of that name
return (self.name == other.name
• This has many problems and self.start == other.start
■ The name tells you nothing and self.salary ==
about its specification other.salary)
Classes and Types 28

You might also like