By the end of this lab, you should have submitted the
lab08
assignment using the command submit lab08
.
This lab is due by 11:59pm on 7/22/2014.
Here is a lab08.py starter file for this lab.
Before you leave lab today, make sure to get Question 1 on the Ants project checked off by either a lab assistant or the TA. Once you walk through your answers to the 6 questions with a lab assistant or TA, give your name and cs61a login (i.e. cs61a-tb) to the person who checked you off and they will record it on the whiteboard. While you are waiting to get checked off, feel free to get started on the lab.
Predict the result of evaluating the following calls in the interpreter. Then try them out yourself! DO NOT SKIP THIS!
>>> class Account(object):
... interest = 0.02
... def __init__(self, account_holder):
... self.balance = 0
... self.holder = account_holder
... def deposit(self, amount):
... self.balance = self.balance + amount
... print("Yes!")
...
>>> a = Account("Billy")
>>> a.account_holder
______
AttributeError: 'Account' object has no attribute 'account_holder'
>>> a.holder
______
'Billy'
>>> class CheckingAccount(Account):
... def deposit(self, amount):
... Account.deposit(self, amount)
... print("Have a nice day!")
...
>>> c = CheckingAccount("Eric")
>>> a.deposit(30)
______
Yes!
>>> c.deposit(30)
______
Yes!
Have a nice day!
Consider the following basic definition of a Person
class:
class Person(object):
def __init__(self, name):
self.name = name
def say(self, stuff):
return stuff
def ask(self, stuff):
return self.say("Would you please " + stuff)
def greet(self):
return self.say("Hello, my name is " + self.name)
Modify this class to add a repeat
method, which repeats the last
thing said. You might have to modify some of the existing methods
to make the repeat
method work. Here's an example of its use:
>>> steven = Person("Steven")
>>> steven.repeat() # starts at whatever value you'd like
'I squirreled it away before it could catch on fire.'
>>> steven.say("Hello")
'Hello'
>>> steven.repeat()
'Hello'
>>> steven.greet()
'Hello, my name is Steven'
>>> steven.repeat()
'Hello, my name is Steven'
>>> steven.ask("preserve abstraction barriers")
'Would you please preserve abstraction barriers'
>>> steven.repeat()
'Would you please preserve abstraction barriers'
class Person(object):
def __init__(self, name):
self.name = name
self.previous = "I squirreled it away before it could catch on fire."
def say(self, stuff):
self.previous = stuff
return stuff
def ask(self, stuff):
return self.say("Would you please " + stuff)
def greet(self):
return self.say("Hello, my name is " + self.name)
def repeat(self):
return self.say(self.previous)
Suppose now that we wanted to define a class called DoubleTalker
to
represent people who always say things twice:
>>> steven = DoubleTalker("Steven")
>>> steven.say("hello")
'hello hello'
>>> steven.say("the sky is falling")
'the sky is falling the sky is falling'
>>> steven.repeat()
'the sky is falling the sky is falling'
Consider the following three definitions for DoubleTalker
:
class DoubleTalker1(Person):
def __init__(self, name):
Person.__init__(self, name)
def say(self, stuff):
return Person.say(self, stuff) + " " + self.repeat()
class DoubleTalker2(Person):
def __init__(self, name):
Person.__init__(self, name)
def say(self, stuff):
return stuff + " " + stuff
class DoubleTalker3(Person):
def __init__(self, name):
Person.__init__(self, name)
def say(self, stuff):
return Person.say(self, stuff + " " + stuff)
DoubleTalker = None # REPLACE ME
Determine which of these definitions work as intended. Also determine
for which of the methods the three versions would respond differently.
(Don't forget about the repeat
method!)
The last one works as intended. For the first and second ones,
calling repeat
would fail.
class DoubleTalker3(Person):
def __init__(self, name):
Person.__init__(self, name)
def say(self, stuff):
return Person.say(self, stuff + " " + stuff)
So you would say
DoubleTalker = DoubleTalker3
Here is another design of the Account
and CheckingAccount
classes:
class Account(object):
"""A bank account that allows deposits and withdrawals."""
interest = 0.02
def __init__(self, account_holder):
self.balance = 0
self.holder = account_holder
def deposit(self, amount):
"""Increase the account balance by amount and return the
new balance."""
self.balance = self.balance + amount
return self.balance
def withdraw(self, amount):
"""Decrease the account balance by amount and return the
new balance."""
if amount > self.balance:
return 'Insufficient funds'
self.balance = self.balance - amount
return self.balance
class CheckingAccount(Account):
"""A bank account that charges for withdrawals."""
withdraw_fee = 1
interest = 0.01
def withdraw(self, amount):
return Account.withdraw(self, amount + self.withdraw_fee)
Modify the code so that both classes have a new attribute,
transactions
, that is a list keeping track of any transactions
performed. For example:
>>> eric_account = Account('Eric')
>>> eric_account.deposit(1000000) # depositing my paycheck for the week
1000000
>>> eric_account.transactions
[(‘deposit’, 1000000)]
>>> eric_account.withdraw(100) # buying dinner
999900
>>> eric_account.transactions
[(‘deposit’, 1000000), (‘withdraw’, 100)]
Don't repeat code if you can help it; use inheritance!
class Account(object):
"""A bank account that allows deposits and withdrawals."""
interest = 0.02
def __init__(self, account_holder):
self.balance = 0
self.holder = account_holder
self.transactions = []
def deposit(self, amount):
"""Increase the account balance by amount and return the new balance."""
self.transactions.append(('deposit', amount))
self.balance = self.balance + amount
return self.balance
def withdraw(self, amount):
"""Decrease the account balance by amount and return the new balance."""
self.transactions.append(('withdraw', amount))
if amount > self.balance:
return 'Insufficient funds'
self.balance = self.balance - amount
return self.balance
class CheckingAccount(Account):
"""A bank account that charges for withdrawals."""
withdraw_fee = 1
interest = 0.01
def withdraw(self, amount):
return Account.withdraw(self, amount + self.withdraw_fee)
We'd like to be able to cash checks, so let's add a deposit_check
method to our CheckingAccount
class. It will take a Check
object
as an argument, and check to see if the payable_to
attribute matches
the CheckingAccount
's holder. If so, it marks the Check
as
deposited, and adds the amount specified to the CheckingAccount
's
total. Here's an example:
>>> check = Check(“Steven”, 42) # 42 dollars, payable to Steven
>>> steven_account = CheckingAccount(“Steven”)
>>> eric_account = CheckingAccount(“Eric”)
>>> eric_account.deposit_check(check) # trying to steal steven’s money
The police have been notified.
>>> eric_account.balance
0
>>> check.deposited
False
>>> steven_account.balance
0
>>> steven_account.deposit_check(check)
42
>>> check.deposited
True
>>> steven_account.deposit_check(check) # can't cash check twice
The police have been notified.
Write an appropriate Check
class, and add the deposit_check
method
to the CheckingAccount
class. Make sure not to copy and paste code!
Use inheritance whenever possible.
class Account(object):
"""A bank account that allows deposits and withdrawals."""
interest = 0.02
def __init__(self, account_holder):
self.balance = 0
self.holder = account_holder
self.transactions = []
def deposit(self, amount):
"""Increase the account balance by amount and return the
new balance."""
self.transactions.append(('deposit', amount))
self.balance = self.balance + amount
return self.balance
def withdraw(self, amount):
"""Decrease the account balance by amount and return the
new balance."""
self.transactions.append(('withdraw', amount))
if amount > self.balance:
return 'Insufficient funds'
self.balance = self.balance - amount
return self.balance
class CheckingAccount(Account):
"""A bank account that charges for withdrawals."""
withdraw_fee = 1
interest = 0.01
def withdraw(self, amount):
return Account.withdraw(self, amount + self.withdraw_fee)
def deposit_check(self, check):
if check.payable_to != self.holder or check.deposited:
print("The police have been notified")
else:
self.deposit(check.amount)
check.deposited = True
class Check(object):
def __init__(self, payable_to, amount):
self.payable_to = payable_to
self.amount = amount
self.deposited = False
We'd like to create a Keyboard
class that takes in an arbitrary number of
Button
s and stores these Button
s in a dictionary. The keys in the
dictionary will be ints that represent the postition on the Keyboard
, and the
values will be the respective Button
. Fill out the methods in the Keyboard
class according to each description, using the doctests as a reference for the
behavior of a Keyboard
.
class Keyboard:
"""A Keyboard takes in an arbitrary amount of buttons, and
has a dictionary of positions as keys, and values as Buttons.
>>> b1 = Button(0, "H")
>>> b2 = Button(1, "I")
>>> k = Keyboard(b1, b2)
>>> k.buttons[0].key
'H'
>>> k.press(1)
'I'
>>> k.typing([0, 1])
'HI'
>>> k.typing([1, 0])
'IH'
>>> b1.pressed
2
>>> b2.pressed
3
"""
def __init__(self, *args):
"*** YOUR CODE HERE ***"
def press(self, info):
"""Takes in a position of the button pressed, and
returns that button's output"""
"*** YOUR CODE HERE ***"
def typing(self, typing_input):
"""Takes in a list of positions of buttons pressed, and
returns the total output"""
"*** YOUR CODE HERE ***"
class Button:
def __init__(self, pos, key):
self.pos = pos
self.key = key
self.pressed = 0
class Keyboard:
"""A Keyboard takes in an arbitrary amount of buttons, and
has a dictionary of positions as keys, and values as Buttons.
>>> b1 = Button(0, "H")
>>> b2 = Button(1, "I")
>>> k = Keyboard(b1, b2)
>>> k.buttons[0].key
'H'
>>> k.press(1)
'I'
>>> k.typing([0, 1])
'HI'
>>> k.typing([1, 0])
'IH'
>>> b1.pressed
2
>>> b2.pressed
3
"""
def __init__(self, *args):
self.buttons = {}
for button in args:
self.buttons[button.pos] = button
def press(self, info):
"""Takes in a position of the button pressed, and
returns that button's output"""
if info in self.buttons.keys():
b = self.buttons[info]
b.pressed += 1
return b.key
return ''
def typing(self, typing_input):
"""Takes in a list of positions of buttons pressed, and
returns the total output"""
accumulate = ''
for pos in typing_input:
accumulate+=self.press(pos)
return accumulate
class Button:
def __init__(self, pos, key):
self.pos = pos
self.key = key
self.pressed = 0
Now that you've implemented a Keyboard
class, write a function that takes in
a list of positions and a Keyboard
and returns what the Keyboard
would
print given the list of inputs. You should be able to do this in one line of
code.
def button_press(positions, keyboard):
"""Takes in a list of positions, and returns what
keyboard would print
>>> b1 = Button(8, "B")
>>> b2 = Button(5, "A")
>>> b3 = Button(1, "N")
>>> kboard = Keyboard(b1, b2, b3)
>>> button_press([8, 5, 1, 5, 1, 5], kboard)
'BANANA'
"""
"*** YOUR CODE HERE ***"
def button_press(positions, keyboard):
"""Takes in a list of positions, and returns what
keyboard would print
>>> b1 = Button(8, "B")
>>> b2 = Button(5, "A")
>>> b3 = Button(1, "N")
>>> kboard = Keyboard(b1, b2, b3)
>>> button_press([8, 5, 1, 5, 1, 5], kboard)
'BANANA'
"""
return keybord.typing(positions)