Introduction to Computer Science II
Homework and Lab 4
Due by 3:10pm on Tuesday, February 3
Reading
Read chapter 8 and the week 4 lecture notes.
Lab
Monday 1:30pm-3:00 in room 512 in 14 E Jackson or via Zoom.
Problems
Solve the following by implementing the corresponding functions in homework4.py. When
done, submit that file through D2L.
1. Implement class SavingsAccount
as a subclass of the class BankAccount you developed in Homework 2. Your
implementation should override the inherited construct method
__init__() and add an additional method addInterest()
using the following specs:
- __init__(): takes as input the interest rate and the
balance (default value 0).
- addInterest(): computes and adds the interest to the
balance
Usage:
>>> s = SavingsAccount(3, 100)
>>> s.balance()
100
>>> s.addInterest()
>>> s.balance()
103.0
>>> s = SavingsAccount(3)
>>> s.deposit(1000)
>>> s.addInterest()
>>> s.balance()
1030.0
2. There are some problems with the
implementation of the class BankAccount from Homework 2, and
they are illustrated here:
>>> x = BankAccount(-700)
>>> x.balance()
-700
>>> x.withdraw(70)
>>> x.balance()
-770
>>> x.deposit(-7)
>>> x.balance()
Balance: -777
The problems are: (1) a bank account with a negative balance can be
created, (2) the withdrawal amount is greater than the balance, and
(3) the deposit amount is negative. Modify the code for the
BankAccount class so that a ValueError exception is
thrown for any of these violations, together with an appropriate
message: 'Illegal balance', 'Overdraft', or 'Negative
deposit'. For example:
Usage:
>>> x = BankAccount2(-700)
Traceback (most recent call last):
...
ValueError: Negative balance
>>> x = BankAccount2(700)
>>> x.withdraw(800)
Traceback (most recent call last):
...
ValueError: Overdraft
>>> x.deposit(-100)
Traceback (most recent call last):
...
ValueError: Negative deposit
3. In problem 2, a generic ValueError
exception is raised if any of the three violations occur. It would
be more useful if a more specific, user-defined exception is raised
instead. Define new exception classes NegativeBalanceError,
OverdraftError, and DepositError that would be
raised instead. In addition, the informal string representation of
the exception object should contain the balance that would result
from the negative balance account creation, the overdraft, or the
negative deposit. For example, when trying to create a bank account
with a negative balance, the error message should include the
balance that would result if the bank account creation was allowed:
>>> x = BankAccount3(-5)
Traceback (most recent call last):
...
NegativeBalanceError: Account created with negative
balance -5
When a withdrawal results in a negative balance, the error message
should also include the balance that would result if the withdrawal
was allowed:
>>> x = BankAccount3(5)
>>> x.withdraw(7)
Traceback (most recent call last):
...
OverdraftError: Operation would result in negative balance -2
If a negative deposit is attempted, the negative deposit amount
should be included in the error message:
>>> x.deposit(-3)
Traceback (most recent call last):
...
DepositError: Negative deposit -3
Finally, reimplement the class BankAccount to use these
new exception classes instead of ValueError.
4. Implement a class myInt
that behaves almost the same as the built-in class int,
except when trying to add an object of type myInt. Then,
this strange behavior occurs:
Usage:
>>> x = myInt(5)
>>> x * 4
20
>>> x * (4 + 6)
50
>>> x + 6
'Whatever ... '
5. Develop a class myList that is
a subclass of the built-in list class. The only dierence
between myList and list is that the sort
method is overridden. myList containers should behave
just like regular lists, except as shown next:
Usage:
>>> x = myList([1, 2, 3])
>>> x
[1, 2, 3]
>>> x.reverse()
>>> x
[3, 2, 1]
>>>
x[2]
1
>>> x.sort()
You wish...
6. Consider the class tree hierarchy:

Implement six classes to model this taxonomy with Python
inheritance. In class Animal, implement method speak()
that will be inherited by the descendant classes of Animal.
In method Mammal, implement method drink() that
will be inherited by the descendents classes of Mammal.
Complete the implementation of the six classes so that they exhibit
this behavior:
Usage:
>>> tweety = Animal()
>>> tweety.speak()
>>> tweety.drink()
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
tweety.drink()
AttributeError: 'Animal' object has no attribute 'drink'
>>> snoopy = Dog()
>>> garfield = Cat()
>>> snoopy.speak()
Wooof!
>>> garfield.speak()
Meeow!
>>> snoopy.drink()
Drinking milk...
>>> dude = Hacker()
>>> dude.speak()
Hello World!
>>> kingkong = Primate()
>>> kingkong.speak()
Boooh
7. [Lab exercise] Implement a
container class called
PriorityQueue. The class should support methods:
- insert(n): Takes a number n as input and adds it to
the container
- min(): Returns the smallest number in the container
- removeMin() Removes the smallest number in the
container
- isEmpty(): Returns True if container is empty, False
otherwise
In addition to these methods your class should support the
overloaded operator len() as shown below.
Usage:
>>> pq = PriorityQueue()
>>> pq.insert(3)
>>> pq.insert(1)
>>> pq.insert(5)
>>> pq.insert(2)
>>> pq.min()
1
>>> pq.removeMin()
>>> pq.min() 2
>>> len(pq)
3
>>> pq.isEmpty()
False
Note: Think about the class invariant. Under the hood, there will be
some type of list to store the numbers in the priority queue.
Consider two possibilities: 1) the list is unsorted and 2) the list
is unsorted. How does your implementation change between the two
class invariants?