Book Class [40 pts]
Write the Book class so that it passes testBookClass, and
uses the OOP constructs we learned this week as appropriate.
def testBookClass():
print("Testing Book class...", end="")
# A Book has a title, and author, and a number of pages.
# It also has a current page, which always starts at 1. There is no page 0!
book1 = Book("Harry Potter and the Sorcerer's Stone",
"J. K. Rowling", 309)
assert(str(book1) == "Book<Harry Potter and the Sorcerer's Stone by " +
"J. K. Rowling: 309 pages, currently on page 1>")
book2 = Book("Carnegie Mellon Motto", "Andrew Carnegie", 1)
assert(str(book2) == "Book<Carnegie Mellon Motto by Andrew Carnegie: " +
"1 page, currently on page 1>")
# You can turn pages in a book. Turning a positive number of pages moves
# forward; turning a negative number moves backwards. You can't move past
# the first page going backwards or the last page going forwards
book1.turnPage(4) # turning pages does not return
assert(book1.getCurrentPage() == 5)
book1.turnPage(-1)
assert(book1.getCurrentPage() == 4)
book1.turnPage(400)
assert(book1.getCurrentPage() == 309)
assert(str(book1) == "Book<Harry Potter and the Sorcerer's Stone by " +
"J. K. Rowling: 309 pages, currently on page 309>")
book2.turnPage(-1)
assert(book2.getCurrentPage() == 1)
book2.turnPage(1)
assert(book2.getCurrentPage() == 1)
# You can also put a bookmark on the current page. This lets you turn
# back to it easily. The book starts out without a bookmark.
book3 = Book("The Name of the Wind", "Patrick Rothfuss", 662)
assert(str(book3) == "Book<The Name of the Wind by Patrick Rothfuss: " + \
"662 pages, currently on page 1>")
assert(book3.getBookmarkedPage() == None)
book3.turnPage(9)
book3.placeBookmark() # does not return
assert(book3.getBookmarkedPage() == 10)
book3.turnPage(7)
assert(book3.getBookmarkedPage() == 10)
assert(book3.getCurrentPage() == 17)
assert(str(book3) == "Book<The Name of the Wind by Patrick Rothfuss: " + \
"662 pages, currently on page 17, page 10 bookmarked>")
book3.turnToBookmark()
assert(book3.getCurrentPage() == 10)
book3.removeBookmark()
assert(book3.getBookmarkedPage() == None)
book3.turnPage(25)
assert(book3.getCurrentPage() == 35)
book3.turnToBookmark() # if there's no bookmark, don't turn to a page
assert(book3.getCurrentPage() == 35)
assert(str(book3) == "Book<The Name of the Wind by Patrick Rothfuss: " + \
"662 pages, currently on page 35>")
# Finally, you should be able to compare two books directly and hash books
book5 = Book("A Game of Thrones", "George R.R. Martin", 807)
book6 = Book("A Game of Thrones", "George R.R. Martin", 807)
book7 = Book("A Natural History of Dragons", "Marie Brennan", 334)
book8 = Book("A Game of Spoofs", "George R.R. Martin", 807)
assert(book5 == book6)
assert(book5 != book7)
assert(book5 != book8)
s = set()
assert(book5 not in s)
s.add(book5)
assert(book6 in s)
assert(book7 not in s)
s.remove(book6)
assert(book5 not in s)
book5.turnPage(1)
assert(book5 != book6)
book5.turnPage(-1)
assert(book5 == book6)
book6.placeBookmark()
assert(book5 != book6)
print("Done!")
Bird Class and Subclasses [35 pts]
Write the Bird, Penguin, and MessengerBird classes so that they pass testBirdClasses and use the OOP constructs we learned this week as appropriate.
def getLocalMethods(clss):
import types
# This is a helper function for the test function below.
# It returns a sorted list of the names of the methods
# defined in a class. It's okay if you don't fully understand it!
result = [ ]
for var in clss.__dict__:
val = clss.__dict__[var]
if (isinstance(val, types.FunctionType)):
result.append(var)
return sorted(result)
def testBirdClasses():
print("Testing Bird classes...", end="")
# A basic Bird has a species name, can fly, and can lay eggs
bird1 = Bird("Parrot")
assert(type(bird1) == Bird)
assert(isinstance(bird1, Bird))
assert(bird1.fly() == "I can fly!")
assert(bird1.countEggs() == 0)
assert(str(bird1) == "Parrot has 0 eggs")
bird1.layEgg()
assert(bird1.countEggs() == 1)
assert(str(bird1) == "Parrot has 1 egg")
bird1.layEgg()
assert(bird1.countEggs() == 2)
assert(str(bird1) == "Parrot has 2 eggs")
assert(getLocalMethods(Bird) == ['__init__', '__repr__', 'countEggs',
'fly', 'layEgg'])
# A Penguin is a Bird that cannot fly, but can swim
bird2 = Penguin("Emperor Penguin")
assert(type(bird2) == Penguin)
assert(isinstance(bird2, Penguin))
assert(isinstance(bird2, Bird))
assert(bird2.fly() == "No flying for me.")
assert(bird2.swim() == "I can swim!")
bird2.layEgg()
assert(bird2.countEggs() == 1)
assert(str(bird2) == "Emperor Penguin has 1 egg")
assert(getLocalMethods(Penguin) == ['fly', 'swim'])
# A MessengerBird is a Bird that can optionally carry a message
bird3 = MessengerBird("War Pigeon", message="Top-Secret Message!")
assert(type(bird3) == MessengerBird)
assert(isinstance(bird3, MessengerBird))
assert(isinstance(bird3, Bird))
assert(not isinstance(bird3, Penguin))
assert(bird3.deliverMessage() == "Top-Secret Message!")
assert(str(bird3) == "War Pigeon has 0 eggs")
assert(bird3.fly() == "I can fly!")
bird4 = MessengerBird("Homing Pigeon")
assert(bird4.deliverMessage() == "")
bird4.layEgg()
assert(bird4.countEggs() == 1)
assert(getLocalMethods(MessengerBird) == ['__init__', 'deliverMessage'])
print("Done!")