## Inheritance

### Question 1: Checking account

Consider the `Account` class provided below, which represents the attributes and behaviors of a bank account.

``````class Account:
"""A bank account that allows deposits and withdrawals.

>>> eric_account = Account('Eric')
>>> eric_account.deposit(1000000)   # depositing my paycheck for the week
1000000
>>> eric_account.transactions
[('deposit', 1000000)]
999900
>>> eric_account.transactions
[('deposit', 1000000), ('withdraw', 100)]
"""

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``````

We want to create a new class called `CheckingAccount` which inherits from `Account`. We'd like to be able to cash checks to our `CheckingAccount`. To do this, you will have to implement the following:

1. Implement the `Check` class's `__init__` and `mark_deposited` methods, which represents a check that can be deposited into an account. Read the doctests in the `Check` class to learn about the behavior of these methods. Hint: Think about what sort of attributes our `Check` class should have.
2. Implement the `CheckingAccount` class's `deposit_check` method. It will take a `Check` object as an argument.

• If the check was already deposited, print `The police have been notified`
• If the check is NOT payable to the checking account holder, print `The police have been notified`
• Otherwise, mark the check as deposited and deposit the amount into the checking account

The doctests for this problem are extremely important and valuable in understanding how this code works and how the `CheckingAccount` and `Check` classes should interact with each other.

``````class Check:
"""A Check object that can be deposited.

>>> eric_check = Check("Eric", 30)  # 30 dollars, payable to Eric
>>> eric_check.payable_to
'Eric'
>>> eric_check.amount
30
>>> eric_check.deposited
False
>>> eric_check.mark_deposited()
>>> eric_check.deposited
True
"""
def __init__(self, payable_to, amount):
self.payable_to = payable_to
self.amount = amount
self.deposited = False
def mark_deposited(self):
self.deposited = True
class CheckingAccount(Account):
"""A bank account that charges for withdrawals and can deposit checks.

>>> 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
>>> steven_account.balance
0
>>> check.deposited
False
>>> eric_account.transactions
[]
>>> steven_account.transactions
[]
>>> steven_account.deposit_check(check)
42
>>> check.deposited
True
>>> steven_account.transactions
[('deposit', 42)]
>>> steven_account.deposit_check(check)  # can't cash check twice
The police have been notified.
>>> steven_account.transactions  # transactions history shouldn't have changed
[('deposit', 42)]
"""
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.mark_deposited()
return self.balance``````

Use OK to test your code:

``python3 ok -q CheckingAccount``

A linked list is either an empty linked list (`Link.empty`) or a first value and the rest of the linked list.

``````class Link:
"""
>>> s
"""
empty = ()

def __init__(self, first, rest=empty):
self.first = first
self.rest = rest

def __repr__(self):
rest_str = ', ' + repr(self.rest)
else:
rest_str = ''

To check if a `Link` is empty, compare it against the class attribute `Link.empty`. For example, the below function prints out whether or not the link it is handed is empty:

``````def test_empty(link):
else:
print('This linked list is not empty!')``````

Note: Linked lists are recursive data structures! A linked list contains the first element of the list (`first`) and a reference to another linked list (`rest`) which contains the rest of the values in the list.

### Question 2: WWPP: Linked Lists

Use OK to test your knowledge with the following "What Would Python Print?" questions:

``python3 ok -q link -u``

If you get stuck, try loading lab08.py into an interpreter or drawing out the diagram for the linked list on a piece of paper.

``````>>> from lab08 import *
______1
______2
______True
______9001
______3
______1
______1
______2
______<1 2 3 4>``````

### Question 3: List to Link

Write a function `list_to_link` that converts a Python list to a `Link`.

``````def list_to_link(lst):
"""Takes a Python list and returns a Link with the same elements.

<1 2 3>
<4>
"""
if not lst:
else:

Use OK to test your code:

``python3 ok -q list_to_link``

### Question 4: Reverse

Implement `reverse`, which takes a linked list `link` and returns a linked list containing the elements of `link` in reverse order. The original `link` should be unchanged.

``````def reverse(link):
"""Returns a Link that is the reverse of the original.

<1>
<3 2 1>
<1 2 3>
"""
#return new

return new

# Recursive solution
return t
else:

Use OK to test your code:

``python3 ok -q reverse``

### Question 5: Slice

Implement a function `slice_link` that slices a given `link`. `slice_link` should slice the `link` starting at `start` and ending one element before `end`, as with slicing a normal Python list.

``````def slice_link(link, start, end):
"""Slices a Link from start to end (as with a normal Python list).

>>> new
``python3 ok -q slice_link``