CMU 15-112: Fundamentals of Programming and Computer Science
Homework 12 (Due Friday 20-Nov at 8pm ET)

  • To start:
    1. Create a folder named 'week12'
    2. Download all of these to that folder:
    3. Edit hw12.py
    4. When you have completed and fully tested hw12, submit hw12.py to Autolab. For this hw, you may submit up to 4 times, but only your last submission counts.
  • Do not hardcode the test cases in your solutions.

    1. Person class [25 pts, autograded]
      Write the class Person so that the following test code passes:
      def testPersonClass():
          print('Testing Person Class...', end='')
          fred = Person('fred', 32)
          assert(isinstance(fred, Person))
          assert(fred.getName() == 'fred')
          assert(fred.getAge() == 32)
          assert(fred.getFriends() == None)
      
          wilma = Person('wilma', 35)
          assert(wilma.getName() == 'wilma')
          assert(wilma.getAge() == 35)
          assert(wilma.getFriends() == None)
      
          wilma.addFriend(fred)
          assert(wilma.getFriends() == [fred])
          assert(fred.getFriends() == None)    # friends are not necessarily reciprocal!
          wilma.addFriend(fred)
          assert(wilma.getFriends() == [fred]) # don't add twice!
      
          barney = Person('barney', 28)
          fred.addFriend(wilma)
          fred.addFriend(barney)
          assert(fred.getFriends() == [wilma, barney])
       
          fred.addFriend(barney)  # don't add twice
          fred.addFriend(fred)    # ignore self as a friend
          assert(fred.getFriends() == [wilma, barney])
          print('Passed!')
      
      Note that your solution must work in general, and not hardcode to these specific test cases.

    2. Bird Class and Subclasses [75 pts, autograded]
      Write the Bird, Penguin, and MessengerBird classes so that they pass testBirdClasses and use the OOP constructs we learned this week as appropriate.
      Note/Hint: getLocalMethods does not include static methods, and startMigrating should be a static method.
      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") tempBird = Bird("Parrot") assert(bird1 == tempBird) tempBird = Bird("Wren") assert(bird1 != tempBird) nest = set() assert(bird1 not in nest) assert(tempBird not in nest) nest.add(bird1) assert(bird1 in nest) assert(tempBird not in nest) nest.remove(bird1) assert(bird1 not in nest) assert(getLocalMethods(Bird) == ['__eq__','__hash__','__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(not isinstance(bird1, Penguin)) 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 carries a message bird3 = MessengerBird("War Pigeon", "Top-Secret Message!") assert(type(bird3) == MessengerBird) assert(isinstance(bird3, MessengerBird)) assert(isinstance(bird3, Bird)) assert(not isinstance(bird3, Penguin)) assert(not isinstance(bird2, MessengerBird)) assert(not isinstance(bird1, MessengerBird)) 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']) # Note: all birds are migrating or not (together, as one) assert(bird1.isMigrating == bird2.isMigrating == bird3.isMigrating == False) assert(Bird.isMigrating == False) bird1.startMigrating() assert(bird1.isMigrating == bird2.isMigrating == bird3.isMigrating == True) assert(Bird.isMigrating == True) Bird.stopMigrating() assert(bird1.isMigrating == bird2.isMigrating == bird3.isMigrating == False) assert(Bird.isMigrating == False) print("Done!") testBirdClasses()