高级编程技术 作业5

##9-1 餐馆 :创建一个名为 Restaurant 的类,其方法 init() 设置两个属性: restaurant_name 和 cuisine_type 。创建一个名为 describe_restaurant() 的方法和一个名为 open_restaurant() 的方法,其中前者打印前述两项信息,而后者打印一条消息,指出餐馆正在营业。

根据这个类创建一个名为 restaurant 的实例,分别打印其两个属性,再调用前述两个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Restaurant():

def __init__(self, restaurant_name, cuisine_type):
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type

def describe_restaurant(self):
print(self.restaurant_name)
print(self.cuisine_type)

def open_restaurant(self):
print("Restaurant is Available")

restaurant = Restaurant('Hi', "What?")
restaurant.describe_restaurant()
restaurant.open_restaurant()

##9-2 三家餐馆 :根据你为完成练习 9-1 而编写的类创建三个实例,并对每个实例调用方法 describe_restaurant() 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Restaurant():

def __init__(self, restaurant_name, cuisine_type):
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type

def describe_restaurant(self):
print(self.restaurant_name)
print(self.cuisine_type)

def open_restaurant(self):
print("Restaurant is Available")

a = Restaurant('a', "aa")
b = Restaurant('b', "bb")
c = Restaurant('c', "cc")
a.describe_restaurant()
b.describe_restaurant()
c.describe_restaurant()

##9-3 用户 :创建一个名为 User 的类,其中包含属性 first_name 和 last_name ,还有用户简介通常会存储的其他几个属性。在类 User 中定义一个名为 describe_user() 的方法,它打印用户信息摘要;再定义一个名为 greet_user() 的方法,它向用户发出个性化的问候。

创建多个表示不同用户的实例,并对每个实例都调用上述两个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class User():

def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name

def describe_user(self):
print(self.first_name)
print(self.last_name)

def greet_user(self):
print("Hello,", self.first_name, self.last_name)

a = User('a', 'aa')
b = User('b', 'bb')
c = User('c', 'cc')
a.describe_user()
a.greet_user()
b.describe_user()
b.greet_user()
c.describe_user()
c.greet_user()

##9-4 就餐人数 :在为完成练习 9-1 而编写的程序中,添加一个名为 number_served 的属性,并将其默认值设置为 0 。根据这个类创建一个名为 restaurant 的实例;打印有多少人在这家餐馆就餐过,然后修改这个值并再次打印它。

添加一个名为 set_number_served() 的方法,它让你能够设置就餐人数。调用这个方法并向它传递一个值,然后再次打印这个值。
添加一个名为 increment_number_served() 的方法,它让你能够将就餐人数递增。调用这个方法并向它传递一个这样的值:你认为这家餐馆每天可能接待的就餐人数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Restaurant():

def __init__(self, restaurant_name, cuisine_type, number_served=0):
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type
self.number_served = number_served

def describe_restaurant(self):
print(self.restaurant_name)
print(self.cuisine_type)

def open_restaurant(self):
print("Restaurant is Available")

def set_number_served(self, number_served):
self.number_served = number_served

def increment_number_served(self, number_served):
self.number_served += number_served

restaurant = Restaurant('a', 'b')
print(restaurant.number_served)
restaurant.number_served = 1
print(restaurant.number_served)
restaurant.set_number_served(2)
print(restaurant.number_served)
restaurant.increment_number_served(3)
print(restaurant.number_served)

##9-5 尝试登录次数 :在为完成练习 9-3 而编写的 User 类中,添加一个名为 login_attempts 的属性。编写一个名为 increment_login_attempts() 的方法,它将属性 login_attempts 的值加 1 。再编写一个名为 reset_login_attempts() 的方法,它将属性 login_attempts 的值重置为 0 。

根据 User 类创建一个实例,再调用方法 increment_login_attempts() 多次。打印属性 login_attempts 的值,确认它被正确地递增;然后,调用方法 reset_login_attempts() ,并再次打印属性 login_attempts 的值,确认它被重置为 0 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class User():

def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
self.login_attempts = 0

def describe_user(self):
print(self.first_name)
print(self.last_name)

def greet_user(self):
print("Hello,", self.first_name, self.last_name)

def increment_login_attempts(self):
self.login_attempts += 1

def reset_login_attempts(self):
self.login_attempts = 0

u = User('a', 'b')
for i in range(5):
u.increment_login_attempts()
print(u.login_attempts)
u.reset_login_attempts()
print(u.login_attempts)

##9-6 冰淇淋小店 :冰淇淋小店是一种特殊的餐馆。编写一个名为 IceCreamStand 的类,让它继承你为完成练习 9-1 或练习 9-4 而编写的 Restaurant 类。这两个版本的 Restaurant 类都可以,挑选你更喜欢的那个即可。添加一个名为 flavors 的属性,用于存储一个由各种口味的冰淇淋组成的列表。编写一个显示这些冰淇淋的方法。创建一个 IceCreamStand 实例,并调用这个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Restaurant():

def __init__(self, restaurant_name, cuisine_type):
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type

def describe_restaurant(self):
print(self.restaurant_name)
print(self.cuisine_type)

def open_restaurant(self):
print("Restaurant is Available")

class IceCreamStand(Restaurant):
def __init__(self, restaurant_name, cuisine_type, flavors):
super().__init__(restaurant_name, cuisine_type)
self.flavors = flavors

def show_flavors(self):
print(self.flavors)

i = IceCreamStand('a', 'b', ['c', 'd', 'e'])
i.show_flavors()

##9-7 管理员 :管理员是一种特殊的用户。编写一个名为 Admin 的类,让它继承你为完成练习 9-3 或练习 9-5 而编写的 User 类。添加一个名为 privileges 的属性,用于存储一个由字符串(如 “can add post” 、 “can delete post” 、 “can ban user” 等)组成的列表。编写一个名为 show_privileges() 的方法,它显示管理员的权限。创建一个 Admin 实例,并调用这个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class User():

def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name

def describe_user(self):
print(self.first_name)
print(self.last_name)

def greet_user(self):
print("Hello,", self.first_name, self.last_name)

class Admin(User):
def __init__(self, first_name, last_name):
super().__init__(first_name, last_name)
self.privileges = ["can add post", "can delete post", "can ban user"]

def show_privileges(self):
print(self.privileges)

a = Admin('a', 'b')
a.show_privileges()

##9-8 权限 :编写一个名为 Privileges 的类,它只有一个属性 —— privileges ,其中存储了练习 9-7 所说的字符串列表。将方法 show_privileges() 移到这个类中。在 Admin 类中,将一个 Privileges 实例用作其属性。创建一个 Admin 实例,并使用方法 show_privileges() 来显示其权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Privileges():
def __init__(self):
self.privileges = ["can add post", "can delete post", "can ban user"]

def show_privileges(self):
print(self.privileges)

class User():

def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name

def describe_user(self):
print(self.first_name)
print(self.last_name)

def greet_user(self):
print("Hello,", self.first_name, self.last_name)

class Admin(User):
def __init__(self, first_name, last_name):
super().__init__(first_name, last_name)
self.privileges = Privileges()

def show_privileges(self):
self.privileges.show_privileges()

a = Admin('a', 'b')
a.show_privileges()

##9-9 电瓶升级 :在本节最后一个 electric_car.py 版本中,给 Battery 类添加一个名为 upgrade_battery() 的方法。这个方法检查电瓶容量,如果它不是 85 ,就将它设置为 85 。创建一辆电瓶容量为默认值的电动汽车,调用方法 get_range() ,然后对电瓶进行升级,并再次调用 get_range() 。你会看到这辆汽车的续航里程增加了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class Battery:
""" 一次模拟电动汽车电瓶的简单尝试 """

def __init__(self, battery_size=70):
""" 初始化电瓶的属性 """
self.battery_size = battery_size

def describe_battery(self):
""" 打印一条描述电瓶容量的消息 """
print("This car has a " + str(self.battery_size) + "-kWh battery.")

def get_range(self):
""" 打印一条消息,指出电瓶的续航里程 """
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range)
message += " miles on a full charge."
print(message)

def upgrade_battery(self):
if self.battery_size != 85:
self.battery_size = 85


class Car:
""" 一次模拟汽车的简单尝试 """

def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0

def get_descriptive_name(self):
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()

def read_odometer(self):
print("This car has " + str(self.odometer_reading) + " miles on it.")

def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")

def increment_odometer(self, miles):
self.odometer_reading += miles


class ElectricCar(Car):
""" 电动汽车的独特之处 """

def __init__(self, make, model, year):
""" 初始化父类的属性 """
super().__init__(make, model, year)
self.baterry = Battery()

e = ElectricCar('a', 'b', 'c')
e.baterry.get_range()
e.baterry.upgrade_battery()
e.baterry.get_range()

##9-10 导入 Restaurant 类 :将最新的 Restaurant 类存储在一个模块中。在另一个文件中,导入 Restaurant 类,创建一个 Restaurant 实例,并调用 Restaurant 的一个方法,以确认 import 语句正确无误。

1
2
3
4
5
6
7
8
9
from restaurant import Restaurant
restaurant = Restaurant('a', 'b')
print(restaurant.number_served)
restaurant.number_served = 1
print(restaurant.number_served)
restaurant.set_number_served(2)
print(restaurant.number_served)
restaurant.increment_number_served(3)
print(restaurant.number_served)

##9-11 导入 Admin 类 :以为完成练习 9-8 而做的工作为基础,将 User 、 Privileges 和 Admin 类存储在一个模块中,再创建一个文件,在其中创建一个 Admin 实例并对其调用方法 show_privileges() ,以确认一切都能正确地运行。

1
2
3
from admin import Admin
a = Admin('a', 'b')
a.show_privileges()

##9-12 多个模块 :将 User 类存储在一个模块中,并将 Privileges 和 Admin 类存储在另一个模块中。再创建一个文件,在其中创建一个 Admin 实例,并对其调用方法 show_privileges() ,以确认一切都依然能够正确地运行。

1
2
3
4
from user import User
from admin import Privileges, Admin
a = Admin('a', 'b')
a.show_privileges()

##9-15 Python Module of the Week :要了解 Python 标准库,一个很不错的资源是网站 Python Module of the Week 。请访问 http://pymotw.com/ 并查看其中的目录,在其中找一个你感兴趣的模块进行探索,或阅读模块 collections 和 random 的文档。

1
https://pymotw.com/3/re/index.html

##10-1 Python 学习笔记 :在文本编辑器中新建一个文件,写几句话来总结一下你至此学到的 Python 知识,其中每一行都以 “In Python you can” 打头。将这个文件命名为learning_python.txt ,并将其存储到为完成本章练习而编写的程序所在的目录中。编写一个程序,它读取这个文件,并将你所写的内容打印三次:第一次打印时读取整个文件;第二次打印时遍历文件对象;第三次打印时将各行存储在一个列表中,再在 with 代码块外打印它们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
file = 'learning_python.txt'
with open(file, 'r', encoding='UTF-8') as f:
m = f.read()
print(m)

with open(file, 'r', encoding='UTF-8') as f:
for line in f:
print(line)

with open(file, 'r', encoding='UTF-8') as f:
ml = f.readlines()

for i in ml:
print(i)

##10-2 C 语言学习笔记 :可使用方法 replace() 将字符串中的特定单词都替换为另一个单词。

读取你刚创建的文件 learning_python.txt 中的每一行,将其中的 Python 都替换为另一门语言的名称,如 C 。将修改后的各行都打印到屏幕上。

1
2
3
4
5
6
file = 'learning_python.txt'
with open(file, 'r', encoding='UTF-8') as f:
ml = f.readlines()
for i in ml:
i = i.replace('Python', 'C')
print(i)

##10-3 访客 :编写一个程序,提示用户输入其名字;用户作出响应后,将其名字写入到文件 guest.txt 中。

1
2
3
n = input("Enter your name:\n")
with open('guest.txt ', 'w') as f:
f.write(n)

##10-4 访客名单 :编写一个 while 循环,提示用户输入其名字。用户输入其名字后,在屏幕上打印一句问候语,并将一条访问记录添加到文件 guest_book.txt 中。确保这个文件中的每条记录都独占一行。

1
2
3
4
5
with open('guest.txt ', 'w') as f:
while True:
n = input("Enter your name:\n")
print("Hello, {}!".format(n))
f.write(n + '\n')

##10-5 关于编程的调查 :编写一个 while 循环,询问用户为何喜欢编程。每当用户输入一个原因后,都将其添加到一个存储所有原因的文件中。

1
2
3
4
with open('reasons.txt ', 'w+') as f:
while True:
n = input("Enter your reason:\n")
f.write(n + '\n')

##10-6 加法运算 :提示用户提供数值输入时,常出现的一个问题是,用户提供的是文本而不是数字。在这种情况下,当你尝试将输入转换为整数时,将引发 TypeError 异常。编写一个程序,提示用户输入两个数字,再将它们相加并打印结果。在用户输入的任何一个值不是数字时都捕获 TypeError 异常,并打印一条友好的错误消息。对你编写的程序进行测试:先输入两个数字,再输入一些文本而不是数字。

1
2
3
4
5
6
a = input('Enter the first number:\n')
b = input('Enter the second number:\n')
try:
print(int(a) + int(b))
except TypeError as e:
print("TypeError!\n", e)

##10-7 加法计算器 :将你为完成练习 10-6 而编写的代码放在一个 while 循环中,让用户犯错(输入的是文本而不是数字)后能够继续输入数字。

1
2
3
4
5
6
7
while True:
a = input('Enter the first number:\n')
b = input('Enter the second number:\n')
try:
print(int(a) + int(b))
except TypeError as e:
print("TypeError!\n", e)

##10-8 猫和狗 :创建两个文件 cats.txt 和 dogs.txt ,在第一个文件中至少存储三只猫的名字,在第二个文件中至少存储三条狗的名字。编写一个程序,尝试读取这些文件,并将其内容打印到屏幕上。将这些代码放在一个 try-except 代码块中,以便在文件不存在时捕获 FileNotFound 错误,并打印一条友好的消息。将其中一个文件移到另一个地方,并确认 except 代码块中的代码将正确地执行。

1
2
3
4
5
6
7
8
9
10
11
12
f1 = 'cats.txt '
f2 = 'dogs.txt'
try:
with open(f1, 'r') as f:
print(f.read())
except FileNotFoundError as e:
print(e)
try:
with open(f2, 'r') as f:
print(f.read())
except FileNotFoundError as e:
print(e)

##10-9 沉默的猫和狗 :修改你在练习 10-8 中编写的 except 代码块,让程序在文件不存在时一言不发。

1
2
3
4
5
6
7
8
9
10
11
f1 = 'cats.txt '
f2 = 'dogs.txt'
try:
with open(f1, 'r') as f:
print(f.read())
except FileNotFoundError as e:

try:
with open(f2, 'r') as f:
print(f.read())
except FileNotFoundError as e:

##10-10 常见单词 :访问项目 Gutenberg ( http://gutenberg.org/ ),并找一些你想分析的图书。下载这些作品的文本文件或将浏览器中的原始文本复制到文本文件中。你可以使用方法 count() 来确定特定的单词或短语在字符串中出现了多少次。例如,下面的代码计算 ‘row’ 在一个字符串中出现了多少次:

编写一个程序,它读取你在项目 Gutenberg 中获取的文件,并计算单词 ‘the’ 在每个文件中分别出现了多少次。

1
2
3
4
5
6
f1 = 'download.txt '
try:
with open(f1, 'r') as f:
print(f.read().lower().count('the'))
except FileNotFoundError as e:
print(e)

##10-11 喜欢的数字 :编写一个程序,提示用户输入他喜欢的数字,并使用 json.dump() 将这个数字存储到文件中。再编写一个程序,从文件中读取这个值,并打印消息 “I know your favorite number! It’s _.” 。

1
2
3
4
5
6
7
8
import json
f1 = 'num.json'
n = input("Enter a number:\n")
with open(f1, 'w') as f:
json.dump(n, f)
with open(f1) as f:
nn = json.load(f)
print("I know your favorite number! It's {}.".format(nn))

##10-12 记住喜欢的数字 :将练习 10-11 中的两个程序合而为一。如果存储了用户喜欢的数字,就向用户显示它,否则提示用户输入他喜欢的数字并将其存储到文件中。运行这个程序两次,看看它是否像预期的那样工作。

1
2
3
4
5
6
7
8
9
10
11
import json
f1 = 'num.json'
try:
with open(f1) as f:
nn = json.load(f)
print("I know your favorite number! It's {}.".format(nn))
except FileNotFoundError as e:

n = input("Enter a number:\n")
with open(f1, 'w') as f:
json.dump(n, f)

##10-13 验证用户 :最后一个 remember_me.py 版本假设用户要么已输入其用户名,要么是首次运行该程序。我们应修改这个程序,以应对这样的情形:当前和最后一次运行该程序的用户并非同一个人。

为此,在 greet_user() 中打印欢迎用户回来的消息前,先询问他用户名是否是对的。如果不对,就调用get_new_username() 让用户输入正确的用户名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import json


def get_stored_username():
""" 如果存储了用户名,就获取它 """
filename = 'username.json'
try:
with open(filename) as f_obj:
username = json.load(f_obj)
except FileNotFoundError:
return None
else:
return username


def get_new_username():
""" 提示用户输入用户名 """

username = input("What is your name? ")
filename = 'username.json'
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
return username


def greet_user():
""" 问候用户,并指出其名字 """
a = input("What's your name?\n")
if a == get_stored_username():
username = get_stored_username()
if username:
print("Welcome back, " + username + "!")
else:
username = get_new_username()
print("We'll remember you when you come back, " + username + "!")
else:
username = get_new_username()
if username:
print("Welcome back, " + username + "!")
else:
username = get_new_username()
print("We'll remember you when you come back, " + username + "!")

greet_user()

##