We now want to write three different classes, Mailman, Client, and Email to simulate email. Fill in the definitions below to finish the implementation! There are more methods to fill out on the next page.
classEmail: """Every email object has 3 instance attributes: the message, the sender name, and the recipient name. """ def__init__(self, msg, sender_name, recipient_name): self.message = msg self.sender_name = sender_name self.recipient_name = recipient_name
classMailman: """Each Mailman has an instance attribute clients, which is a dictionary that associates client names with client objects. """ def__init__(self): self.clients = {} defsend(self, email): """Take an email and put it in the inbox of the client it is addressed to. """ client = self.clients[email.recipient_name] client.receive(email)
defregister_client(self, client, client_name): """Takes a client object and client_name and adds it to the clients instance attribute. """ self.clients[client_name] = client
classClient: """Every Client has instance attributes name (which is used for addressing emails to the client), mailman (which is used to send emails out to other clients), and inbox (a list of all emails the client has received). """ def__init__(self, mailman, name): self.inbox = [] self.name = name self.mailman = mailman self.mailman.register_client(self, self.name) defcompose(self, msg, recipient_name): """Send an email with the given message msg to the given recipient client. """ email = Email(msg, self.name, recipient_name) self.mailman.send(email) defreceive(self, email): """Take an email and add it to the inbox of this client. """ self.inbox.append(email)
Inheritance
Python classes can implement a useful abstraction technique known as inheritance. To illustrate this concept, consider the following Dog and Cat classes.
Notice that because dogs and cats share a lot of similar qualities, there is a lot of repeated code! To avoid redefining attributes and methods for similar classes, we can write a single superclass from which the similar classes inherit. For example, we can write a class called Pet and redefine Dog as a subclass of Pet:
1 2 3 4 5 6 7 8 9 10 11 12 13
classPet(object): def__init__(self, name, owner): self.is_alive = True# It's alive!!! self.name = name self.owner = owner defeat(self, thing): print(self.name + " ate a " + str(thing) + "!") deftalk(self): print(self.name)
Inheritance represents a hierarchical relationship between two or more classes where one class is a more specific version of the other, e.g. a dog is a pet. Because Dog inherits from Pet, we didn’t have to redefine init or eat. However, since we want Dog to talk in a way that is unique to dogs, we did override the talk method.
Questions
2.1 Below is a skeleton for the Cat class, which inherits from the Pet class. To complete the implementation, override the __init__ and talk methods and add a new lose_life method. Hint: You can call the init method of Pet to set a cat’s name and owner.
classCat(Pet): def__init__(self, name, owner, lives=9): Pet.__init__(self, name, owner) self.lives = lives deftalk(self): """ Print out a cat's greeting. >>> Cat('Thomas', 'Tammy').talk() Thomas says meow! """ print(self.name + ' says meow!') deflose_life(self): """Decrements a cat's life by 1. When lives reaches zero, 'is_alive' becomes False. """ if self.lives > 0: self.lives -= 1 if self.lives == 0: returnFalse else: print("This cat has no more lives to lose!")
2.2 More cats! Fill in this implemention of a class called NoisyCat, which is just like a normal Cat. However, NoisyCat talks a lot – twice as much as a regular Cat!
1 2 3 4 5 6 7 8 9 10 11 12 13
classNoisyCat(Cat): # Fill me in! """A Cat that repeats things twice.""" def__init__(self, name, owner, lives=9): # Is this method necessary? Why or why not? Cat.__init__(self, name, owner, lives) deftalk(self): """Talks twice as much as a regular cat. >>> NoisyCat('Magic', 'James').talk() Magic says meow! Magic says meow! """ for _ inrange(2): Cat.talk(self)