[2021 Spring] CS61A Discussion 6: Object-Oriented Programming, Iterators and Generators
discussion 6: https://inst.eecs.berkeley.edu/~cs61a/sp21/disc/disc06/#q2
Q2: (Tutorial) Email
通过三个不同的类 (Server, Client, and Email) 来模拟邮件系统。
建议的处理路线:Email类 → Server类的客户端注册方法 → Client类 → Server类的send方法。
思路:
- 每个email对象有三个实例属性: 信息、发件人名称、收件人名称
- 客户端注册:创建client对象时,调用Server的register_client方法,将client对象和client name放入服务器的clients字典中。
- Client类的compose方法:整合信息msg,传入收件人,创建email实例,调用Server的send方法。
- Server的send方法根据传入的email对象收件人,调用receive方法收到inbox里。
OOP的第一个问题,
class Email:
"""Every email object has 3 instance attributes: the
message, the sender name, and the recipient name.
"""
def __init__(self, msg, sender_name, recipient_name):
"*** YOUR CODE HERE ***"
self.msg = msg
self.sender_name = sender_name
self.recipient_name = recipient_name
class Server:
"""Each Server has an instance attribute clients, which
is a dictionary that associates client names with
client objects.
"""
def __init__(self):
self.clients = {}
def send(self, email):
"""Take an email and put it in the inbox of the client
it is addressed to.
"""
"*** YOUR CODE HERE ***"
self.clients[email.recipient_name].receive(email)
def register_client(self, client, client_name):
"""Takes a client object and client_name and adds them
to the clients instance attribute.
"""
"*** YOUR CODE HERE ***"
self.clients[client_name] = client
class Client:
"""Every Client has instance attributes name (which is
used for addressing emails to the client), server
(which is used to send emails out to other clients), and
inbox (a list of all emails the client has received).
>>> s = Server()
>>> a = Client(s, 'Alice')
>>> b = Client(s, 'Bob')
>>> a.compose('Hello, World!', 'Bob')
>>> b.inbox[0].msg
'Hello, World!'
>>> a.compose('CS 61A Rocks!', 'Bob')
>>> len(b.inbox)
2
>>> b.inbox[1].msg
'CS 61A Rocks!'
"""
def __init__(self, server, name):
self.inbox = []
"*** YOUR CODE HERE ***"
self.server = server
self.name = name
server.register_client(self, name)
def compose(self, msg, recipient_name):
"""Send an email with the given message msg to the
given recipient client.
"""
"*** YOUR CODE HERE ***"
self.server.send(Email(msg, self.name, recipient_name))
def receive(self, email):
"""Take an email and add it to the inbox of this
client.
"""
"*** YOUR CODE HERE ***"
self.inbox.append(email)
Q3: Cat
一般来说,子类中定义super().init__是不必要的,因为创建实例时会自动调用父类的__init。在子类中需要额外操作,比如添加新的实例变量时,才会调用super().init。
class Pet():
def __init__(self, name, owner):
self.is_alive = True # It's alive!!!
self.name = name
self.owner = owner
def eat(self, thing):
print(self.name + " ate a " + str(thing) + "!")
def talk(self):
print(self.name)
class Cat(Pet):
def __init__(self, name, owner, lives=9):
"*** YOUR CODE HERE ***"
super().__init__(name, owner)
self.lives = lives
def talk(self):
""" Print out a cat's greeting.
>>> Cat('Thomas', 'Tammy').talk()
Thomas says meow!
"""
"*** YOUR CODE HERE ***"
print(self.name + ' says meow!')
def lose_life(self):
"""Decrements a cat's life by 1. When lives reaches zero, 'is_alive'
becomes False. If this is called after lives has reached zero, print out
that the cat has no more lives to lose.
"""
"*** YOUR CODE HERE ***"
self.lives -= 1
if self.lives == 0:
self.is_alive = False
elif self.lives < 0:
print('the cat has no more lives to lose.')
Q4: (Tutorial) NoisyCat
"*** YOUR CODE HERE ***"
class NoisyCat(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?
"*** YOUR CODE HERE ***"
# Not necessary
super().__init__(name, owner, lives)
def talk(self):
"""Talks twice as much as a regular cat.
>>> NoisyCat('Magic', 'James').talk()
Magic says meow!
Magic says meow!
"""
"*** YOUR CODE HERE ***"
print(self.name + ' says meow!')
print(self.name + ' says meow!')
Q6: Filter-Iter
def filter_iter(iterable, fn):
"""
>>> is_even = lambda x: x % 2 == 0
>>> list(filter_iter(range(5), is_even)) # a list of the values yielded from the call to filter_iter
[0, 2, 4]
>>> all_odd = (2*y-1 for y in range(5))
>>> list(filter_iter(all_odd, is_even))
[]
>>> naturals = (n for n in range(1, 100))
>>> s = filter_iter(naturals, is_even)
>>> next(s)
2
>>> next(s)
4
"""
"*** YOUR CODE HERE ***"
for x in iterable:
if fn(x):
yield x