《Python编程:从入门到实践》课后习题及答案

第 1 章 起步

1-1 python.org:浏览Python主页(http://python.org/),寻找你感兴趣的主题。你对Python越熟悉,这个网站对你来说就越有用。

1-2 输入错误:打开你刚创建的文件hello_world.py,在代码中添加一个输入错误,再运行这个程序。输入错误会引发错误吗?你能理解显示的错误消息吗?你能添加一个不会导致错误的输入错误吗?你凭什么认为它不会导致错误?

1-3 无穷的技艺:如果你编程技艺无穷,你打算开发什么样的程序呢?你就要开始学习编程了;如果心中有目标,就能立即将新学到的技能付诸应用;现在正是草拟目标的大好时机。将想法记录下来是个不错的习惯,这样每当需要开始新项目时,都可参考它们。现在请花点时间描绘三个你想创建的程序。

 


第2章 变量和简单数据类型

在Python中使用变量时,需要遵守一些规则和指南。违反这些规则将引发错误,而指南旨在让你编写的代码更容易阅读和理解。请务必牢记下述有关变量的规则。

  • 变量名只能包含字母、数字和下划线。变量名可以字母或下划线打头,但不能以数字打头,例如,可将变量命名为message_1,但不能将其命名为1_message。

  • 变量名不能包含空格,但可使用下划线来分隔其中的单词。例如,变量名greeting_message可行,但变量名greeting message会引发错误。

  • 不要将Python关键字和函数名用作变量名,即不要使用Python保留用于特殊用途的单词,如print(请参见附录A.4)。

  • 变量名应既简短又具有描述性。例如,name比n好,student_name比s_n好,name_length比length_of_persons_name好。

  • 慎用小写字母l和大写字母O,因为它们可能被人错看成数字1和0

动手试一试

请完成下面的练习,在做每个练习时,都编写一个独立的程序。保存每个程序时,使用符合标准Python约定的文件名:使用小写字母和下划线,如simple_message.py和simple_messages.py。

2-1 简单消息:将一条消息存储到变量中,再将其打印出来。

message = "hello  world!"
print(message)

=================== RESTART: C:/ProgramFiles/Python38/test.py ==================
hello  world!

2-2 多条简单消息:将一条消息存储到变量中,将其打印出来;再将变量的值修改为一条新消息,并将其打印出来。

message = "hello world!"
print(message)
message = "world hello!"
print(message)

 

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
hello world!
world hello!

  在Python中,用引号括起的都是字符串,其中的引号可以是单引号,也可以是双引号。

在做下面的每个练习时,都编写一个独立的程序,并将其保存为名称类似于name_cases.py的文件。如果遇到了困难,请休息一会儿或参阅附录C提供的建议。

 

2-3 个性化消息:将用户的姓名存到一个变量中,并向该用户显示一条消息。显示的消息应非常简单,如“Hello Eric, would you like to learn some Python today?”。

name = "Eric"
message = "hello! " + name + ",would you like to learn some Python today?"
print(message) 

 

========== RESTART: C:/ProgramFiles/Python/Python36/message_case.py ==========
hello! Eric,would you like to learn some Python today?

 

2-4 调整名字的大小写:将一个人名存储到一个变量中,再以小写、大写和首字母大写的方式显示这个人名。

name = "smith"
print(name.upper())
print(name.lower())
print(name.title())

 

========== RESTART: C:/ProgramFiles/Python/Python36/message_case.py ==========
SMITH
smith
Smith

 

2-5 名言:找一句你钦佩的名人说的名言,将这个名人的姓名和他的名言打印出来。输出应类似于下面这样(包括引号):

Albert Einstein once said, “A person who never made a mistake never tried anything new.”

print('Albert Einstein once said, “A person who never made a mistake never tried anything new.” ') 

 

========== RESTART: C:/ProgramFiles/Python/Python36/message_case.py ==========
Albert Einstein once said, “A person who never made a mistake never tried anything new.”

 

2-6 名言2:重复练习2-5,但将名人的姓名存储在变量famous_person中,再创建要显示的消息,并将其存储在变量message中,然后打印这条消息。

famous_person = "Albert Einstein"
message = famous_person + ' once said, "A person who never made a mistake never tried anything new."'
print(message)

 

========== RESTART: C:/ProgramFiles/Python/Python36/message_case.py ==========
Albert Einstein once said, "A person who never made a mistake never tried anything new."

 

2-7 剔除人名中的空白:存储一个人名,并在其开头和末尾都包含一些空白字符。务必至少使用字符组合"\t""\n"各一次。

打印这个人名,以显示其开头和末尾的空白。然后,分别使用剔除函数lstrip()rstrip()strip()对人名进行处理,并将结果打印出来。

name = "\n\tAlbert Einstein\t\n"
print(name)
print(name.lstrip())
print(name.rstrip())
print(name.strip()) 

 

========== RESTART: C:/ProgramFiles/Python/Python36/message_case.py ==========

    Albert Einstein    

Albert Einstein    


    Albert Einstein
Albert Einstein

动手试一试

2-8 数字8:编写4个表达式,它们分别使用加法、减法、乘法和除法运算,但结果都是数字8。为使用print语句来显示结果,务必将这些表达式用括号括起来,也就是说,你应该编写4行类似于下面的代码:

print(5 + 3)

输出应为4行,其中每行都只包含数字8。

print(5 + 3)
print(11 - 3)
print(2 * 4)
print(int(24 / 3)) 

 

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
8
8
8
8

 

2-9 最喜欢的数字:将你最喜欢的数字存储在一个变量中,再使用这个变量创建一条消息,指出你最喜欢的数字,然后将这条消息打印出来。

number = 8
print("my favorite number is " + str(number)) 

 

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
my favorite number is 8

 

动手试一试

2-10 添加注释:选择你编写的两个程序,在每个程序中都至少添加一条注释。如果程序太简单,实在没有什么需要说明的,就在程序文件开头加上你的姓名和当前日期,再用一句话阐述程序的功能。

 

动手试一试

2-11 Python之禅:在Python终端会话中执行命令import this,并粗略地浏览一下其他的指导原则。

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

 

在本章中,你学习了:如何使用变量;如何创建描述性变量名以及如何消除名称错误和语法错误;字符串是什么,以及如何使用小写、大写和首字母大写方式显示字符串;使用空白来显示整洁的输出,以及如何剔除字符串中多余的空白;如何使用整数和浮点数;使用数值数据时需要注意的意外行为。你还学习了如何编写说明性注释,让代码对你和其他人来说更容易理解。最后,你了解了让代码尽可能简单的理念。

在第3章,你将学习如何在被称为列表的变量中存储信息集,以及如何通过遍历列表来操作其中的信息。

 


 

第 3 章 列表简介

动手试一试

请尝试编写一些简短的程序来完成下面的练习,以获得一些使用Python列表的第一手经验。你可能需要为每章的练习创建一个文件夹,以整洁有序的方式存储为完成各章的练习而编写的程序。

3-1 姓名:将一些朋友的姓名存储在一个列表中,并将其命名为names。依次访问该列表中的每个元素,从而将每个朋友的姓名都打印出来。

names = ["xiaoming", "john", "jack", "eric"]
print(names[0], names[1], names[2], names[3])

 

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
xiaoming john jack eric

 

3-2 问候语:继续使用练习3-1中的列表,但不打印每个朋友的姓名,而为每人打印一条消息。每条消息都包含相同的问候语,但抬头为相应朋友的姓名。

names = ["xiaoming", "john", "jack", "eric"]
message = "nice to meet you! "
print(message + names[0])
print(message + names[1])
print(message + names[2])
print(message + names[3])

 

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
nice to meet you! xiaoming
nice to meet you! john
nice to meet you! jack
nice to meet you! eric

 

3-3 自己的列表:想想你喜欢的通勤方式,如骑摩托车或开汽车,并创建一个包含多种通勤方式的列表。根据该列表打印一系列有关这些通勤方式的宣言,如“I would like to own a Honda motorcycle”。

1 lists = ["car", "plane", "rocket"]
2 print("I would like to own a " + lists[0])
3 print("I would like to own a " + lists[1])
4 print("I would like to own a " + lists[2])

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
I would like to own a car
I would like to own a plane
I would like to own a rocket

 注意 方法remove()只删除第一个指定的值。如果要删除的值可能在列表中出现多次,就需要使用循环来判断是否删除了所有这样的值。你将在第7章学习如何这样做。

 

动手试一试

 

下面的练习比第2章的练习要复杂些,但让你有机会以前面介绍过的各种方式使用列表。

 

3-4 嘉宾名单:如果你可以邀请任何人一起共进晚餐(无论是在世的还是故去的),你会邀请哪些人?请创建一个列表,其中包含至少3个你想邀请的人;然后,使用这个列表打印消息,邀请这些人来与你共进晚餐。

1 names = ["马云", "马化腾", "马斯克"]
2 print("尊敬的: " + names[0] +", "+ names[1]+", "+ names[2]+", " + "请来参加我的慈善晚宴!")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
尊敬的: 马云, 马化腾, 马斯克, 请来参加我的慈善晚宴!

 

 

3-5 修改嘉宾名单:你刚得知有位嘉宾无法赴约,因此需要另外邀请一位嘉宾。

 

  • 以完成练习3-4时编写的程序为基础,在程序末尾添加一条print语句,指出哪位嘉宾无法赴约。

  • 修改嘉宾名单,将无法赴约的嘉宾的姓名替换为新邀请的嘉宾的姓名。

  • 再次打印一系列消息,向名单中的每位嘉宾发出邀请。

1 names = ["马云", "马化腾", "马斯克"]
2 
3 name_absent = names.pop(1)
4 names.insert(1, "马蓉")
5 
6 print("尊敬的: " + names[0] +", "+ names[1]+", "+ names[2]+", " + "请来参加我的慈善晚宴!")
7 
8 print("由于" + name_absent + "帮我打怪练级去了,所以我们又邀请了" + names[1])

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
尊敬的: 马云, 马克思, 马斯克, 请来参加我的慈善晚宴!
由于马化腾帮我打怪练级去了,所以我们又邀请了马蓉

 

3-6 添加嘉宾:你刚找到了一个更大的餐桌,可容纳更多的嘉宾。请想想你还想邀请哪三位嘉宾。

 

  • 以完成练习3-4或练习3-5时编写的程序为基础,在程序末尾添加一条print语句,指出你找到了一个更大的餐桌。

  • 使用insert()将一位新嘉宾添加到名单开头。

  • 使用insert()将另一位新嘉宾添加到名单中间。

  • 使用append()将最后一位新嘉宾添加到名单末尾。

  • 打印一系列消息,向名单中的每位嘉宾发出邀请。

1 names = ["马云", "马化腾", "马斯克"]
2 
3 names.insert(0, "马蓉")
4 names.insert(2,"马东敏")
5 names.append("马拉多纳")
6 
7 for name in names:
8     print("尊敬的:" + name + ", 请来参加我的慈善晚宴!")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
尊敬的:马蓉, 请来参加我的慈善晚宴!
尊敬的:马云, 请来参加我的慈善晚宴!
尊敬的:马东敏, 请来参加我的慈善晚宴!
尊敬的:马化腾, 请来参加我的慈善晚宴!
尊敬的:马斯克, 请来参加我的慈善晚宴!
尊敬的:马拉多纳, 请来参加我的慈善晚宴!

 

 

3-7 缩减名单:你刚得知新购买的餐桌无法及时送达,因此只能邀请两位嘉宾。

 

  • 以完成练习3-6时编写的程序为基础,在程序末尾添加一行代码,打印一条你只能邀请两位嘉宾共进晚餐的消息。

  • 使用pop()不断地删除名单中的嘉宾,直到只有两位嘉宾为止。每次从名单中弹出一位嘉宾时,都打印一条消息,让该嘉宾知悉你很抱歉,无法邀请他来共进晚餐。

  • 对于余下的两位嘉宾中的每一位,都打印一条消息,指出他依然在受邀人之列。

  • 使用del将最后两位嘉宾从名单中删除,让名单变成空的。打印该名单,核实程序结束时名单确实是空的

 1 names = ["马云", "马化腾", "马斯克"]
 2 
 3 names.insert(0, "马蓉")
 4 names.insert(2,"马东敏")
 5 names.append("马拉多纳")
 6 
 7 print(names.pop() + ", 很抱歉,位置不够,你不能来参加了!")
 8 print(names.pop() + ", 很抱歉,位置不够,你不能来参加了!")
 9 print(names.pop() + ", 很抱歉,位置不够,你不能来参加了!")
10 print(names.pop() + ", 很抱歉,位置不够,你不能来参加了!")
11 
12 for name in names:
13     print("尊敬的:" + name + ", 请来参加我的慈善晚宴!")
14 
15 del names[1]
16 del names[0]
17 
18 print(names)

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
马拉多纳, 很抱歉,位置不够,你不能来参加了!
马斯克, 很抱歉,位置不够,你不能来参加了!
马化腾, 很抱歉,位置不够,你不能来参加了!
马东敏, 很抱歉,位置不够,你不能来参加了!
尊敬的:马蓉, 请来参加我的慈善晚宴!
尊敬的:马云, 请来参加我的慈善晚宴!
[]

 

动手试一试

3-8 放眼世界:想出至少5个你渴望去旅游的地方。

  • 将这些地方存储在一个列表中,并确保其中的元素不是按字母顺序排列的。

  • 按原始排列顺序打印该列表。不要考虑输出是否整洁的问题,只管打印原始Python列表。

  • 使用sorted()按字母顺序打印这个列表,同时不要修改它。

  • 再次打印该列表,核实排列顺序未变。

  • 使用sorted()按与字母顺序相反的顺序打印这个列表,同时不要修改它。

  • 再次打印该列表,核实排列顺序未变。

  • 使用reverse()修改列表元素的排列顺序。打印该列表,核实排列顺序确实变了。

  • 使用reverse()再次修改列表元素的排列顺序。打印该列表,核实已恢复到原来的排列顺序。

  • 使用sort()修改该列表,使其元素按字母顺序排列。打印该列表,核实排列顺序确实变了。

 1 places = ["London", "Paris", "Hong Kong", "Beijing", "Shanghai"]
 2 
 3 print(places, "按原始排列顺序打印该列表。")
 4 print(sorted(places), "使用sorted()按字母顺序打印这个列表,同时不要修改它。")
 5 print(places, "再次打印该列表,核实排列顺序未变。")
 6 print(sorted(places, reverse = True), "使用sorted()按与字母顺序相反的顺序打印这个列表,同时不要修改它。")
 7 print(places,"再次打印该列表,核实排列顺序未变。")
 8 places.reverse()
 9 print(places, "使用reverse()修改列表元素的排列顺序。打印该列表,核实排列顺序确实变了。")
10 places.reverse()
11 print(places, "使用reverse()再次修改列表元素的排列顺序。打印该列表,核实已恢复到原来的排列顺序。")
12 places.sort()
13 print(places, "使用sort()修改该列表,使其元素按字母顺序排列。打印该列表,核实排列顺序确实变了。")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
['London', 'Paris', 'Hong Kong', 'Beijing', 'Shanghai'] 按原始排列顺序打印该列表。
['Beijing', 'Hong Kong', 'London', 'Paris', 'Shanghai'] 使用sorted()按字母顺序打印这个列表,同时不要修改它。
['London', 'Paris', 'Hong Kong', 'Beijing', 'Shanghai'] 再次打印该列表,核实排列顺序未变。
['Shanghai', 'Paris', 'London', 'Hong Kong', 'Beijing'] 使用sorted()按与字母顺序相反的顺序打印这个列表,同时不要修改它。
['London', 'Paris', 'Hong Kong', 'Beijing', 'Shanghai'] 再次打印该列表,核实排列顺序未变。
['Shanghai', 'Beijing', 'Hong Kong', 'Paris', 'London'] 使用reverse()修改列表元素的排列顺序。打印该列表,核实排列顺序确实变了。
['London', 'Paris', 'Hong Kong', 'Beijing', 'Shanghai'] 使用reverse()再次修改列表元素的排列顺序。打印该列表,核实已恢复到原来的排列顺序。
['Beijing', 'Hong Kong', 'London', 'Paris', 'Shanghai'] 使用sort()修改该列表,使其元素按字母顺序排列。打印该列表,核实排列顺序确实变了。

 

动手试一试

3-11 有意引发错误:如果你还没有在程序中遇到过索引错误,就尝试引发一个这种错误。在你的一个程序中,修改其中的索引,以引发索引错误。关闭程序前,务必消除这个错误。

在本章中,你学习了:列表是什么以及如何使用其中的元素;如何定义列表以及如何增删元素;如何对列表进行永久性排序,以及如何为展示列表而进行临时排序;如何确定列表的长度,以及在使用列表时如何避免索引错误。

在第4章,你将学习如何以更高效的方式处理列表元素。通过使用为数不多的几行代码来遍历列表元素,你就能高效地处理它们,即便列表包含数千乃至数百万个元素。


 

第 4 章 操作列表

动手试一试

4-1 比萨:想出至少三种你喜欢的比萨,将其名称存储在一个列表中,再使用for循环将每种比萨的名称都打印出来。

  • 修改这个for循环,使其打印包含比萨名称的句子,而不仅仅是比萨的名称。对于每种比萨,都显示一行输出,如“I like pepperoni pizza”。

  • 在程序末尾添加一行代码,它不在for循环中,指出你有多喜欢比萨。输出应包含针对每种比萨的消息,还有一个总结性句子,如“I really love pizza!”。

1 pizzas = ["New Orleans", "Cheese Lover", "Delicious Bacon"]
2 for pizza in pizzas:
3     print(pizza)
4     print("I like " + pizza + "pizza")
5 print("I really love pizza!")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
New Orleans
I like New Orleanspizza
Cheese Lover
I like Cheese Loverpizza
Delicious Bacon
I like Delicious Baconpizza
I really love pizza!

 

4-2 动物:想出至少三种有共同特征的动物,将这些动物的名称存储在一个列表中,再使用for循环将每种动物的名称都打印出来。

  • 修改这个程序,使其针对每种动物都打印一个句子,如“A dog would make a great pet”。

在程序末尾添加一行代码,指出这些动物的共同之处,如打印诸如“Any of these animals would make a great pet!”这样的句子。

1 animals = ["bird", "dog", "cat"]
2 
3 for animal in animals:
4     print("A " + animal + " would make a great pet")
5 
6 print("Any of these animals would make a great pet!")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
A bird would make a great pet
A dog would make a great pet
A cat would make a great pet
Any of these animals would make a great pet!

4-3 数到20:使用一个for循环打印数字1~20(含)。

1 for number in range(1, 21):
2     print(number, end=', ')

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,

4-4 一百万:创建一个列表,其中包含数字1~1 000 000,再使用一个for循环将这些数字打印出来(如果输出的时间太长,按Ctrl + C停止输出,或关闭输出窗口)。

1 numbers = list(range(1, 1000001))
2 
3 for number in numbers:
4     print(number)

 

4-5 计算1~1 000 000的总和:创建一个列表,其中包含数字1~1 000 000,再使用min()max()核实该列表确实是从1开始,到1 000 000结束的。另外,对这个列表调用函数sum(),看看Python将一百万个数字相加需要多长时间。

1 numbers = list(range(1, 1000001))
2 print(min(numbers))
3 print(max(numbers))
4 print(sum(numbers))

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
1
1000000
500000500000

 

4-6 奇数:通过给函数range()指定第三个参数来创建一个列表,其中包含1~20的奇数;再使用一个for循环将这些数字都打印出来。

1 numbers = list(range(1, 20, 2))
2 for digital in numbers:
3     print(digital, end = ', ')

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
1, 3, 5, 7, 9, 11, 13, 15, 17, 19,

 

4-7 3的倍数:创建一个列表,其中包含3~30内能被3整除的数字;再使用一个for循环将这个列表中的数字都打印出来。

1 numbers = list(range(3, 31, 3))
2 for digital in numbers:
3     print(digital, end = ', ')

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
3, 6, 9, 12, 15, 18, 21, 24, 27, 30,

 

4-8 立方:将同一个数字乘三次称为立方。例如,在Python中,2的立方用2**3表示。请创建一个列表,其中包含前10个整数(即1~10)的立方,再使用一个for循环将这些立方数都打印出来。

1 numbers = list(range(1, 11))
2 for digital in numbers:
3     print(digital ** 3, end = ', ')

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
1, 8, 27, 64, 125, 216, 343, 512, 729, 1000,

 

4-9 立方解析:使用列表解析生成一个列表,其中包含前10个整数的立方。

1 a =[digital ** 3 for digital in range(1,11)]
2 print(a)

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

 

动手试一试

4-10 切片:选择你在本章编写的一个程序,在末尾添加几行代码,以完成如下任务。

  • 打印消息“The first three items in the list are:”,再使用切片来打印列表的前三个元素。

  • 打印消息“Three items from the middle of the list are:”,再使用切片来打印列表中间的三个元素。

  • 打印消息“The last three items in the list are:”,再使用切片来打印列表末尾的三个元素。

 1 numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 2 print("“The first three items in the list are:”")
 3 for number in numbers[:3]:
 4     print(number, end = " ")
 5 
 6 print("\n“Three items from the middle of the list are:”")
 7 for number in numbers[1:4]:
 8     print(number, end = " ")
 9 
10 print("\n“The last three items in the list are:”")
11 for number in numbers[-3:]:
12     print(number, end = " ")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
“The first three items in the list are:”
1 2 3
“Three items from the middle of the list are:”
2 3 4
“The last three items in the list are:”
8 9 10

 

4-11 你的比萨和我的比萨:在你为完成练习4-1而编写的程序中,创建比萨列表的副本,并将其存储到变量friend_pizzas中,再完成如下任务。

  • 在原来的比萨列表中添加一种比萨。

  • 在列表friend_pizzas中添加另一种比萨。

  • 核实你有两个不同的列表。为此,打印消息“My favorite pizzas are:”,再使用一个for循环来打印第一个列表;打印消息“My friend's favorite pizzas are:”,再使用一个for循环来打印第二个列表。核实新增的比萨被添加到了正确的列表中。

 1 pizzas = ["New Orleans", "Cheese Lover", "Delicious Bacon"]
 2 friend_pizzas = pizzas[:]
 3 
 4 pizzas.append("durian")
 5 friend_pizzas.append("Black Pepper Beef")
 6 
 7 print("My favorite pizzas are:")
 8 for pizza in pizzas:
 9     print(pizza, end=", ")
10 
11 print("\n\nMy friend's favorite pizzas are:")
12 for pizza in friend_pizzas:
13     print(pizza, end=", ")    

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
My favorite pizzas are:
New Orleans, Cheese Lover, Delicious Bacon, durian,

My friend's favorite pizzas are:
New Orleans, Cheese Lover, Delicious Bacon, Black Pepper Beef,

 

4-12 使用多个循环:在本节中,为节省篇幅,程序foods.py的每个版本都没有使用for循环来打印列表。请选择一个版本的foods.py,在其中编写两个for循环,将各个食品列表都打印出来。

 

4-13 自助餐:有一家自助式餐馆,只提供五种简单的食品。请想出五种简单的食品,并将其存储在一个元组中。

  • 使用一个for循环将该餐馆提供的五种食品都打印出来。

  • 尝试修改其中的一个元素,核实Python确实会拒绝你这样做。

  • 餐馆调整了菜单,替换了它提供的其中两种食品。请编写一个这样的代码块:给元组变量赋值,并使用一个for循环将新元组的每个元素都打印出来。

1 pizzas = ("New Orleans", "Cheese", "Bacon", "Beef", "durian")
2 for pizza in pizzas:
3     print(pizza, end= ", ")
4 print("\n")
5 #pizzas[1] = "chicken"
6 
7 pizzas = ("New Orleans", "Cheese", "Bacon", "chicken", "pig")
8 for pizza in pizzas:
9     print(pizza, end= ", ")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
New Orleans, Cheese, Bacon, Beef, durian,

New Orleans, Cheese, Bacon, chicken, pig,

 

动手试一试

4-14 PEP 8:请访问https://python.org/dev/peps/pep-0008/,阅读PEP 8格式设置指南。当前,这些指南适用的不多,但你可以大致浏览一下。

4-15 代码审核:从本章编写的程序中选择三个,根据PEP 8指南对它们进行修改。

  • 每级缩进都使用四个空格。对你使用的文本编辑器进行设置,使其在你按Tab键时都插入四个空格;如果你还没有这样做,现在就去做吧(有关如何设置,请参阅附录B)。

  • 每行都不要超过80字符。对你使用的编辑器进行设置,使其在第80个字符处显示一条垂直参考线。

  • 不要在程序文件中过多地使用空行。

 

在本章中,你学习了:如何高效地处理列表中的元素;如何使用for循环遍历列表,Python如何根据缩进来确定程序的结构以及如何避免一些常见的缩进错误;如何创建简单的数字列表,以及可对数字列表执行的一些操作;如何通过切片来使用列表的一部分和复制列表。你还学习了元组(它对不应变化的值提供了一定程度的保护),以及在代码变得越来越复杂时如何设置格式,使其易于阅读。

在第5章中,你将学习如何使用if语句在不同的条件下采取不同的措施;学习如何将一组较复杂的条件测试组合起来,并在满足特定条件时采取相应的措施。你还将学习如何在遍历列表时,通过使用if语句对特定元素采取特定的措施。

 

第 5 章 if语句

5-1 条件测试:编写一系列条件测试;将每个测试以及你对其结果的预测和实际结果都打印出来。你编写的代码应类似于下面这样:

car = 'subaru'
print("Is car == 'subaru'? I predict True.")
print(car == 'subaru')
    
print("\nIs car == 'audi'? I predict False.")
print(car == 'audi')详细研究实际结果,直到你明白了它为何为TrueFalse
  • 创建至少10个测试,且其中结果分别为TrueFalse的测试都至少有5个。

5-2 更多的条件测试:你并非只能创建10个测试。如果你想尝试做更多的比较,可再编写一些测试,并将它们加入到conditional_tests.py中。对于下面列出的各种测试,至少编写一个结果为TrueFalse的测试。

  • 检查两个字符串相等和不等。

  • 使用函数lower()的测试。

  • 检查两个数字相等、不等、大于、小于、大于等于和小于等于。

  • 使用关键字andor的测试。

  • 测试特定的值是否包含在列表中。

  • 测试特定的值是否未包含在列表中。

  else是一条包罗万象的语句,只要不满足任何ifelif中的条件测试,其中的代码就会执行,这可能会引入无效甚至恶意的数据。如果知道最终要测试的条件,应考虑使用一个elif代码块来代替else代码块。这样,你就可以肯定,仅当满足相应的条件时,你的代码才会执行。

  if-elif-else结构功能强大,但仅适合用于只有一个条件满足的情况:遇到通过了的测试后,Python就跳过余下的测试。这种行为很好,效率很高,让你能够测试一个特定的条件。

  然而,有时候必须检查你关心的所有条件。在这种情况下,应使用一系列不包含elifelse代码块的简单if语句。在可能有多个条件为True,且你需要在每个条件为True时都采取相应措施时,适合使用这种方法。

 

5-3 外星人颜色#1:假设在游戏中刚射杀了一个外星人,请创建一个名为alien_color的变量,并将其设置为'green''yellow''red'

  • 编写一条if语句,检查外星人是否是绿色的;如果是,就打印一条消息,指出玩家获得了5个点。

  • 编写这个程序的两个版本,在一个版本中上述测试通过了,而在另一个版本中未通过(未通过测试时没有输出)。

1 alien_color = "green"
2 if alien_color == "green":
3     print("you got 5 points")
4 
5 alien_color = "red"
6 if alien_color =="green":
7     print("you got 5 points")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
you got 5 points

 

5-4 外星人颜色#2:像练习5-3那样设置外星人的颜色,并编写一个if-else结构。

  • 如果外星人是绿色的,就打印一条消息,指出玩家因射杀该外星人获得了5个点。

  • 如果外星人不是绿色的,就打印一条消息,指出玩家获得了10个点。

  • 编写这个程序的两个版本,在一个版本中执行if代码块,而在另一个版本中执行else代码块。

 1 alien_color = "green"
 2 if alien_color == "green":
 3     print("you got 5 points!")
 4 else:
 5     print("you got 10 points!")
 6 
 7 alien_color = "red"
 8 print("\nanother test:")
 9 if alien_color =="green":
10     print("you got 5 points")
11 else:
12     print("you got 10 points!")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
you got 5 points!

another test:
you got 10 points!

 

5-5 外星人颜色#3:将练习5-4中的if-else结构改为if-elif-else结构。

  • 如果外星人是绿色的,就打印一条消息,指出玩家获得了5个点。

  • 如果外星人是黄色的,就打印一条消息,指出玩家获得了10个点。

  • 如果外星人是红色的,就打印一条消息,指出玩家获得了15个点。

  • 编写这个程序的三个版本,它们分别在外星人为绿色、黄色和红色时打印一条消息。

 1 alien_color = "green"
 2 if alien_color == "green":
 3     print("you got 5 points!")
 4 elif alien_color =="yellow":
 5     print("you got 10 points!")
 6 elif alien_color =="red":
 7     print("you got 15 points!")
 8 
 9 alien_color = "yellow"
10 print("\nanother test:")
11 if alien_color == "green":
12     print("you got 5 points!")
13 elif alien_color =="yellow":
14     print("you got 10 points!")
15 elif alien_color =="red":
16     print("you got 15 points!")
17 
18 alien_color = "red"
19 print("\nanother test:")
20 if alien_color == "green":
21     print("you got 5 points!")
22 elif alien_color =="yellow":
23     print("you got 10 points!")
24 elif alien_color =="red":
25     print("you got 15 points!")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
you got 5 points!

another test:
you got 10 points!

another test:
you got 15 points!

 

5-6 人生的不同阶段:设置变量age的值,再编写一个if-elif-else结构,根据age的值判断处于人生的哪个阶段。

  • 如果一个人的年龄小于2岁,就打印一条消息,指出他是婴儿。

  • 如果一个人的年龄为2(含)~4岁,就打印一条消息,指出他正蹒跚学步。

  • 如果一个人的年龄为4(含)~13岁,就打印一条消息,指出他是儿童。

  • 如果一个人的年龄为13(含)~20岁,就打印一条消息,指出他是青少年。

  • 如果一个人的年龄为20(含)~65岁,就打印一条消息,指出他是成年人。

  • 如果一个人的年龄超过65(含)岁,就打印一条消息,指出他是老年人。

 

5-7 喜欢的水果:创建一个列表,其中包含你喜欢的水果,再编写一系列独立的if语句,检查列表中是否包含特定的水果。

  • 将该列表命名为favorite_fruits,并在其中包含三种水果。

  • 编写5条if语句,每条都检查某种水果是否包含在列表中,如果包含在列表中,就打印一条消息,如“You really like bananas!”。

 1 favorite_fruits = ["apple","orange","peach"]
 2 if "apple" in favorite_fruits:
 3     print("You really like apples!")
 4 if "orange" in favorite_fruits:
 5     print("You really like oranges!")
 6 if "peach" in favorite_fruits:
 7     print("You really like peachs!")
 8 if "banana" in favorite_fruits:
 9     print("You really like bananas!")
10 if "pear" in favorite_fruits:
11     print("You really like pears!")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
You really like apples!
You really like oranges!
You really like peachs!

 

动手试一试

5-8 以特殊方式跟管理员打招呼:创建一个至少包含5个用户名的列表,且其中一个用户名为'admin'。想象你要编写代码,在每位用户登录网站后都打印一条问候消息。遍历用户名列表,并向每位用户打印一条问候消息。

  • 如果用户名为'admin',就打印一条特殊的问候消息,如“Hello admin, would you like to see a status report?”。

  • 否则,打印一条普通的问候消息,如“Hello Eric, thank you for logging in again”。

1 user_list = ["john", "admin", "jack"]
2 
3 for user in user_list:
4     if user == "admin":
5         print("Hello %s, would you like to see a status report?"%user)
6     else:
7         print(f"Hello {user}, thank you for logging in again")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
Hello john, thank you for logging in again
Hello admin, would you like to see a status report?
Hello jack, thank you for logging in again

 

5-9 处理没有用户的情形:在为完成练习5-8编写的程序中,添加一条if语句,检查用户名列表是否为空。

  • 如果为空,就打印消息“We need to find some users!”。

  • 删除列表中的所有用户名,确定将打印正确的消息。

 1 user_list = ["john", "admin", "jack"]
 2 
 3 if user_list:
 4     for user in user_list:
 5         if user == "admin":
 6             print("Hello %s, would you like to see a status report?"%user)
 7         else:
 8             print(f"Hello {user}, thank you for logging in again")
 9 else:
10     print("We need to find some users!")
11 
12 
13 user_list = []
14 
15 if user_list:
16     for user in user_list:
17         if user == "admin":
18             print("Hello %s, would you like to see a status report?"%user)
19         else:
20             print(f"Hello {user}, thank you for logging in again")
21 else:
22     print("We need to find some users!")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
Hello john, thank you for logging in again
Hello admin, would you like to see a status report?
Hello jack, thank you for logging in again
We need to find some users!

5-10 检查用户名:按下面的说明编写一个程序,模拟网站确保每位用户的用户名都独一无二的方式。

  • 创建一个至少包含5个用户名的列表,并将其命名为current_users

  • 再创建一个包含5个用户名的列表,将其命名为new_users,并确保其中有一两个用户名也包含在列表current_users中。

  • 遍历列表new_users,对于其中的每个用户名,都检查它是否已被使用。如果是这样,就打印一条消息,指出需要输入别的用户名;否则,打印一条消息,指出这个用户名未被使用。

  • 确保比较时不区分大小写;换句话说,如果用户名'John'已被使用,应拒绝用户名'JOHN'

1 current_users = ["john", "admin", "jack", "eric", "alice"]
2 new_users = ["smith", "Eric", "bob", "john", "michael"]
3 
4 for new_user in new_users:
5     if new_user.lower() in current_users:
6         print(f"{new_user} has used!")
7     else:
8         print(f"{new_user} not used!")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
smith not used!
Eric has used!
bob not used!
john has used!
michael not used!

 

5-11 序数:序数表示位置,如1st和2nd。大多数序数都以th结尾,只有1、2和3例外。

  • 在一个列表中存储数字1~9。

  • 遍历这个列表。

  • 在循环中使用一个if-elif-else结构,以打印每个数字对应的序数。输出内容应为1st2nd3rd4th5th6th7th8th9th,但每个序数都独占一行。

 1 digitals = list(range(1, 10))
 2 for digital in digitals:
 3     if digital == 1:
 4         print("%dst"%digital, end=", ")
 5     elif digital == 2:
 6         print(f"{digital}nd", end=", ")
 7     elif digital == 3:
 8         print("{}rd".format(digital), end=", ")
 9     else:
10         print(str(digital) + "th", end=", ")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
1st, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th,

 

动手试一试

5-12 设置if语句的格式:审核你在本章编写的程序,确保正确地设置了条件测试的格式。

5-13 自己的想法:与刚拿起本书时相比,现在你是一名能力更强的程序员了。鉴于你对如何在程序中模拟现实情形有了更深入的认识,你可以考虑使用程序来解决一些问题。随着编程技能不断提高,你可能想解决一些问题,请将这方面的想法记录下来。想想你可能想编写的游戏、想研究的数据集以及想创建的Web应用程序。

 

第 6 章 字典

动手试一试

6-1 人:使用一个字典来存储一个熟人的信息,包括名、姓、年龄和居住的城市。该字典应包含键first_namelast_nameagecity。将存储在该字典中的每项信息都打印出来。

1 person = {
2     "first_name": "john",
3     "last_name": "smith",
4     "age": 18,
5     "city": "beijing"
6     }
7 print(person["first_name"], person["last_name"], person["age"], person["city"])

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
john smith 18 beijing

 

6-2 喜欢的数字:使用一个字典来存储一些人喜欢的数字。请想出5个人的名字,并将这些名字用作字典中的键;想出每个人喜欢的一个数字,并将这些数字作为值存储在字典中。打印每个人的名字和喜欢的数字。为让这个程序更有趣,通过询问朋友确保数据是真实的。

6-3 词汇表:Python字典可用于模拟现实生活中的字典,但为避免混淆,我们将后者称为词汇表。

  • 想出你在前面学过的5个编程词汇,将它们用作词汇表中的键,并将它们的含义作为值存储在词汇表中。

  • 以整洁的方式打印每个词汇及其含义。为此,你可以先打印词汇,在它后面加上一个冒号,再打印词汇的含义;也可在一行打印词汇,再使用换行符(\n)插入一个空行,然后在下一行以缩进的方式打印词汇的含义。

1 dicts = {'list': '列表', 'str': '字符串', 'tuple': '元组', 'dict': '字典', 'int': '整型' }
2 print('list' + ": " + dicts['list'] )
3 print('str' + ": " + dicts['str'] )
4 print('tuple' + ": " + dicts['tuple'] )
5 print('dict' + ": " + dicts['dict'] )
6 print('int' + ": " + dicts['int'] )

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
list: 列表
str: 字符串
tuple: 元组
dict: 字典
int: 整型

 

动手试一试

6-4 词汇表2:既然你知道了如何遍历字典,现在请整理你为完成练习6-3而编写的代码,将其中的一系列print语句替换为一个遍历字典中的键和值的循环。确定该循环正确无误后,再在词汇表中添加5个Python术语。当你再次运行这个程序时,这些新术语及其含义将自动包含在输出中。

 1 dicts = {'list': '列表', 'str': '字符串', 'tuple': '元组', 'dict': '字典', 'int': '整型' }
 2 for key, value in dicts.items():    
 3     print(f"{key}: {value}")
 4     
 5 dicts['split'] = '切片'
 6 dicts['if'] =  '条件'
 7 dicts['class'] = ''
 8 dicts['object'] = '对象'
 9 dicts['boolean'] = '布尔'
10 
11 for key, value in dicts.items():
12     print(f"{key}: {value}")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
list: 列表
str: 字符串
tuple: 元组
dict: 字典
int: 整型
list: 列表
str: 字符串
tuple: 元组
dict: 字典
int: 整型
split: 切片
if: 条件
class: 类
object: 对象
boolean: 布尔

 

6-5 河流:创建一个字典,在其中存储三条大河流及其流经的国家。其中一个键—值对可能是'nile': 'egypt'

  • 使用循环为每条河流打印一条消息,如“The Nile runs through Egypt.”。

  • 使用循环将该字典中每条河流的名字都打印出来。

  • 使用循环将该字典包含的每个国家的名字都打印出来。

1 dics = {'nile': 'egypt', 'long river': 'china', 'amazon': 'brazil' }
2 
3 for key, value in dics.items():
4     print("the %s runs through %s"%(key.title(), value.title()))
5 
6 for value in set(dics.values()):
7     print(value.title())

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
the Nile runs through Egypt
the Long River runs through China
the Amazon runs through Brazil
Egypt
Brazil
China

 

6-6 调查:在6.3.1节编写的程序favorite_languages.py中执行以下操作。

  • 创建一个应该会接受调查的人员名单,其中有些人已包含在字典中,而其他人未包含在字典中。

  • 遍历这个人员名单,对于已参与调查的人,打印一条消息表示感谢。对于还未参与调查的人,打印一条消息邀请他参与调查。

 1 favorite_languages = {
 2     'jen': 'python',
 3     'sarah': 'c',
 4     'edward': 'ruby',
 5     'phil': 'python',
 6     }
 7 
 8 names = ['john', 'jen', 'phil', 'alice', 'eric']
 9 
10 for name in names:
11     if name in favorite_languages.keys():
12         print('thank you! %s'%(name.title()))
13     else:
14         print('{}, please!'.format(name.title()))

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
John, please!
thank you! Jen
thank you! Phil
Alice, please!
Eric, please!

 

动手试一试

6-7 人:在为完成练习6-1而编写的程序中,再创建两个表示人的字典,然后将这三个字典都存储在一个名为people的列表中。遍历这个列表,将其中每个人的所有信息都打印出来。

 

 1 p1 = {
 2     "first_name": "john",
 3     "last_name": "smith",
 4     "age": 18,
 5     "city": "beijing"
 6     }
 7 
 8 p2 = {
 9     "first_name": "jack",
10     "last_name": "london",
11     "age": 30,
12     "city": "london"
13     }
14 
15 p3 = {
16     "first_name": "michael",
17     "last_name": "jackson",
18     "age": 65,
19     "city": "paris"
20     }
21 
22 
23 peoples = [p1, p2, p3]
24 
25 for people in peoples:
26     for key,value in people.items():
27         print(f"{key}: {value}")
28     print('---------------------')

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
first_name: john
last_name: smith
age: 18
city: beijing
first_name: jack
last_name: london
age: 30
city: london
first_name: michael
last_name: jackson
age: 65
city: paris
>>>
============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
first_name: john
last_name: smith
age: 18
city: beijing
---------------------
first_name: jack
last_name: london
age: 30
city: london
---------------------
first_name: michael
last_name: jackson
age: 65
city: paris
---------------------

 

6-8 宠物:创建多个字典,对于每个字典,都使用一个宠物的名称来给它命名;在每个字典中,包含宠物的类型及其主人的名字。将这些字典存储在一个名为pets的列表中,再遍历该列表,并将宠物的所有信息都打印出来。

 1 xiaomao = {'type': 'cat', 'master': 'xiaoming'}
 2 xiaogou = {'type': 'dog', 'master': 'xiaohong'}
 3 xiaoji = {'type': 'chicken', 'master': 'xiaojun'}
 4 
 5 pets = [xiaomao, xiaogou, xiaoji]
 6 
 7 for pet in pets:
 8     for key, value in pet.items():
 9         print("{0} : {1}".format(key, value))
10     print("--------------------------")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
type : cat
master : xiaoming
--------------------------
type : dog
master : xiaohong
--------------------------
type : chicken
master : xiaojun
--------------------------

 

6-9 喜欢的地方:创建一个名为favorite_places的字典。在这个字典中,将三个人的名字用作键;对于其中的每个人,都存储他喜欢的1~3个地方。为让这个练习更有趣些,可让一些朋友指出他们喜欢的几个地方。遍历这个字典,并将其中每个人的名字及其喜欢的地方打印出来。

1 favorite_places = {'jack':['beijing', 'tianjing'], 'john': ['guangzhou','shenzhen',
2                    'zhuhai'],   'alice': ['shanghai', 'suzhou', 'wuxi']}
3 
4 for key,values in favorite_places.items():
5     print(f"{key}'s favorite pleaces is :", end=' ')
6     for value in values:
7         print(value, end=',')
8     print("\n----------------------------------------------------")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
jack's favorite pleaces is : beijing,tianjing,
----------------------------------------------------
john's favorite pleaces is : guangzhou,shenzhen,zhuhai,
----------------------------------------------------
alice's favorite pleaces is : shanghai,suzhou,wuxi,
----------------------------------------------------

 

6-10 喜欢的数字:修改为完成练习6-2而编写的程序,让每个人都可以有多个喜欢的数字,然后将每个人的名字及其喜欢的数字打印出来。

 

6-11 城市:创建一个名为cities的字典,其中将三个城市名用作键;对于每座城市,都创建一个字典,并在其中包含该城市所属的国家、人口约数以及一个有关该城市的事实。在表示每座城市的字典中,应包含countrypopulationfact等键。将每座城市的名字以及有关它们的信息都打印出来。

 1 cities = {
 2     'shanghai':{'country':'china','popultion': '10000'},
 3     'new york':{'country':'american','popultion': '1000'},
 4     'london':{'country':'english','popultion': '100'}
 5     }
 6 
 7 for key, value in cities.items():
 8     print(key + ":")
 9     for key1,value1 in value.items():
10         print(f"{key1}: {value1}")
11     print('--------------------------------')

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
shanghai:
country: china
popultion: 10000
--------------------------------
new york:
country: american
popultion: 1000
--------------------------------
london:
country: english
popultion: 100
--------------------------------

6-12 扩展:本章的示例足够复杂,可以以很多方式进行扩展了。请对本章的一个示例进行扩展:添加键和值、调整程序要解决的问题或改进输出的格式。

在本章中,你学习了:如何定义字典,以及如何使用存储在字典中的信息;如何访问和修改字典中的元素,以及如何遍历字典中的所有信息;如何遍历字典中所有的键-值对、所有的键和所有的值;如何在列表中嵌套字典、在字典中嵌套列表以及在字典中嵌套字典。

在下一章中,你将学习while循环以及如何从用户那里获取输入。这是激动人心的一章,让你知道如何将程序变成交互性的——能够对用户输入作出响应。

第 7 章 用户输入和while循环

7-1 汽车租赁:编写一个程序,询问用户要租赁什么样的汽车,并打印一条消息,如“Let me see if I can find you a Subaru”。

1 car = input("which car do you like? > ")
2 print(f"Let me see if I can find you a {car}")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
which car do you like? > bmw
Let me see if I can find you a bmw

 

7-2 餐馆订位:编写一个程序,询问用户有多少人用餐。如果超过8人,就打印一条消息,指出没有空桌;否则指出有空桌。

1 number = input('how many people ? > ')
2 number = int(number)
3 if number > 8:
4     print("get out!")
5 else:
6     print("come in!")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
how many people ? > 8
come in
>>>
============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
how many people ? > 9
get out!

7-3 10的整数倍:让用户输入一个数字,并指出这个数字是否是10的整数倍。

1 number = int(input('digital,please: '))
2 if number % 10 == 0:
3     print('just it!')
4 else:
5     print('NO!')

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
digital,please: 10
just it!
>>>
============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
digital,please: 3
NO!
>>>
============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
digital,please: 33
NO!

 

动手试一试

7-4 比萨配料:编写一个循环,提示用户输入一系列的比萨配料,并在用户输入'quit'时结束循环。每当用户输入一种配料后,都打印一条消息,说我们会在比萨中添加这种配料。

 1 active = True
 2 
 3 while active:
 4     prompt = "\nPlease enter the topping:"
 5     prompt += "\n(Enter 'quit' when you are finished.) >  "
 6     topping = input(prompt)
 7 
 8     if topping == 'quit':
 9         active = False
10     else:
11         print(f"ok,{topping} will be added!")

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============

Please enter the topping:
(Enter 'quit' when you are finished.) >  beef
ok,beef will be added!

Please enter the topping:
(Enter 'quit' when you are finished.) >  quit

 

7-5 电影票:有家电影院根据观众的年龄收取不同的票价:不到3岁的观众免费;3~12岁的观众为10美元;超过12岁的观众为15美元。请编写一个循环,在其中询问用户的年龄,并指出其票价。

 1 while True:
 2     prompt = "\nPlease enter your age:"
 3     prompt += "\n(Enter 'quit' when you are finished.) >  "
 4     age = input(prompt)
 5 
 6     if age == "quit":
 7         print("bye!")
 8         break
 9     elif int(age) < 3:
10         print("free!")
11     elif int(age) <= 12:
12         print("10 dollars!")
13     elif int(age) > 12:
14         print("15 dollars!")

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============

Please enter your age:
(Enter 'quit' when you are finished.) >  12
10 dollars!

Please enter your age:
(Enter 'quit' when you are finished.) >  3
10 dollars!

Please enter your age:
(Enter 'quit' when you are finished.) >  2
free!

Please enter your age:
(Enter 'quit' when you are finished.) >  quit
bye!

7-6 三个出口:以另一种方式完成练习7-4或练习7-5,在程序中采取如下所有做法。

  • while循环中使用条件测试来结束循环。

  • 使用变量active来控制循环结束的时机。

  • 使用break语句在用户输入'quit'时退出循环。

 1 topping = ""
 2 active = True
 3 
 4 prompt = "\nPlease enter the topping:"
 5 prompt += "\n(Enter 'quit' when you are finished.) >  "
 6 
 7 print("------------------first-------------------")
 8 while topping != "quit":
 9     topping = input(prompt)
10     if topping != "quit":       
11         print(f"ok,{topping} will be added!")
12 
13 print("\n------------------second-------------------")
14 while active:
15     topping = input(prompt)
16     if topping == "quit":
17         active = False
18     else:
19         print(f"ok,{topping} will be added!")        
20 
21 print("\n------------------third-------------------")
22 while True:
23     topping = input(prompt)
24     if topping == "quit":
25         break
26     else:
27         print(f"ok,{topping} will be added!")

 

7-7 无限循环:编写一个没完没了的循环,并运行它(要结束该循环,可按Ctrl +C,也可关闭显示输出的窗口)。

 

动手试一试

7-8 熟食店:创建一个名为sandwich_orders的列表,在其中包含各种三明治的名字;再创建一个名为finished_sandwiches的空列表。遍历列表sandwich_orders,对于其中的每种三明治,都打印一条消息,如I made your tuna sandwich,并将其移到列表finished_sandwiches。所有三明治都制作好后,打印一条消息,将这些三明治列出来。

7-9 五香烟熏牛肉(pastrami)卖完了:使用为完成练习7-8而创建的列表sandwich_orders,并确保'pastrami'在其中至少出现了三次。在程序开头附近添加这样的代码:打印一条消息,指出熟食店的五香烟熏牛肉卖完了;再使用一个while循环将列表sandwich_orders中的'pastrami'都删除。确认最终的列表finished_sandwiches中不包含'pastrami'

7-10 梦想的度假胜地:编写一个程序,调查用户梦想的度假胜地。使用类似于“If you could visit one place in the world, where would you go?”的提示,并编写一个打印调查结果的代码块。

在本章中,你学习了:如何在程序中使用input()来让用户提供信息;如何处理文本和数字输入,以及如何使用while循环让程序按用户的要求不断地运行;多种控制while循环流程的方式:设置活动标志、使用break语句以及使用continue语句;如何使用while循环在列表之间移动元素,以及如何从列表中删除所有包含特定值的元素;如何结合使用while循环和字典。

在第8章中,你将学习函数。函数让你能够将程序分成多个很小的部分,其中每部分都负责完成一项具体任务。你可以根据需要调用同一个函数任意次,还可将函数存储在独立的文件中。使用函数可让你编写的代码效率更高,更容易维护和排除故障,还可在众多不同的程序中重用。

 

第 8 章 函数

动手试一试

8-1 消息:编写一个名为display_message()的函数,它打印一个句子,指出你在本章学的是什么。调用这个函数,确认显示的消息正确无误。

1 def display_message():
2     print("function!")
3 
4 display_message()

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
function!

8-2 喜欢的图书:编写一个名为favorite_book()的函数,其中包含一个名为title的形参。这个函数打印一条消息,如One of my favorite books is Alice in Wonderland。调用这个函数,并将一本图书的名称作为实参传递给它。

1 def favorite_book(title):
2     print(f"One of my favorite books is {title}。")
3 
4 favorite_book("Alice in Wonderland")

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
One of my favorite books is Alice in Wonderland。

 

8-3 T恤:编写一个名为make_shirt()的函数,它接受一个尺码以及要印到T恤上的字样。这个函数应打印一个句子,概要地说明T恤的尺码和字样。

使用位置实参调用这个函数来制作一件T恤;再使用关键字实参来调用这个函数。

1 def make_shirt(size, message):
2     print(f"your shirt's size is {size}, and the message is {message}")
3 
4 make_shirt(1, "hello1")
5 make_shirt(size=2, message="hello2")
6 make_shirt(message="hello3", size=3)

>>>
============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
your shirt's size is 1, and the message is hello1
your shirt's size is 2, and the message is hello2
your shirt's size is 3, and the message is hello3

 

8-4 大号T恤:修改函数make_shirt(),使其在默认情况下制作一件印有字样“I love Python”的大号T恤。调用这个函数来制作如下T恤:一件印有默认字样的大号T恤、一件印有默认字样的中号T恤和一件印有其他字样的T恤(尺码无关紧要)。

1 def make_shirt(size="big", message="i love python"):
2     print(f"your shirt's size is {size}, and the message is {message}")
3 
4 make_shirt()
5 make_shirt(size="middle")
6 make_shirt(message="hello3", size=3)

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
your shirt's size is big, and the message is i love python
your shirt's size is middle, and the message is i love python
your shirt's size is 3, and the message is hello3

 

8-5 城市:编写一个名为describe_city()的函数,它接受一座城市的名字以及该城市所属的国家。这个函数应打印一个简单的句子,如Reykjavik is in Iceland。给用于存储国家的形参指定默认值。为三座不同的城市调用这个函数,且其中至少有一座城市不属于默认国家。

1 def describe_city(city, country="china"):
2     print(f"{city} is in {country}")
3 
4 describe_city("reykjavik", "iceland")
5 describe_city("beijing")
6 describe_city("shanghai", "china")  

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
reykjavik is in iceland
beijing is in china
shanghai is in china

 

8-6 城市名:编写一个名为city_country()的函数,它接受城市的名称及其所属的国家。这个函数应返回一个格式类似于下面这样的字符串:

   "Santiago, Chile"

至少使用三个城市-国家对调用这个函数,并打印它返回的值。

1 def city_country(city, country):
2     message = city +', ' + country
3     return message
4 
5 print(city_country("Santiago", "Chile"))
6 print(city_country("london", "england"))
7 print(city_country("beijing", "china")

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
Santiago, Chile
london, england
beijing, china

 

8-7 专辑:编写一个名为make_album()的函数,它创建一个描述音乐专辑的字典。这个函数应接受歌手的名字和专辑名,并返回一个包含这两项信息的字典。使用这个函数创建三个表示不同专辑的字典,并打印每个返回的值,以核实字典正确地存储了专辑的信息。

给函数make_album()添加一个可选形参,以便能够存储专辑包含的歌曲数。如果调用这个函数时指定了歌曲数,就将这个值添加到表示专辑的字典中。调用这个函数,并至少在一次调用中指定专辑包含的歌曲数。

 1 def make_album(singer, album, number=""):
 2     album = {'album_name': album, 'singer_name': singer}
 3     if number:
 4         album["number"] = number
 5     return album
 6 
 7 album1 = make_album("A", "aa")
 8 print(album1)
 9 
10 album2 = make_album("A", "aa", '3')
11 print(album2)

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
{'album_name': 'aa', 'singer_name': 'A'}
{'album_name': 'aa', 'singer_name': 'A', 'number': '3'}

 

8-8 用户的专辑:在为完成练习8-7编写的程序中,编写一个while循环,让用户输入一个专辑的歌手和名称。获取这些信息后,使用它们来调用函数make_album(),并将创建的字典打印出来。在这个while循环中,务必要提供退出途径。

 1 def make_album(singer, album, number=""):
 2     album = {'album_name': album, 'singer_name': singer}
 3     if number:
 4         album["number"] = number
 5     return album
 6 
 7 while True:
 8     print("\nplease enter the album information:")
 9     print("(enter 'q' at any to quit.)")
10 
11     album_name = input("album name: > ")
12     if album_name == 'q':
13         break
14   
15     singer_name = input("singer name: > ")
16     if singer_name == 'q':
17         break
18 
19     a = make_album(album_name, singer_name)
20     print(a)

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============

please enter the album information:
(enter 'q' at any to quit.)
album name: > ab
singer name: > cd
{'album_name': 'cd', 'singer_name': 'ab'}

please enter the album information:
(enter 'q' at any to quit.)
album name: > q

动手试一试

8-9 魔术师:创建一个包含魔术师名字的列表,并将其传递给一个名为show_magicians()的函数,这个函数打印列表中每个魔术师的名字。

1 magician_list = ['a','b','c']
2 
3 def show_magicians(magicians):
4     for magician in magicians:
5         print(magician)
6 
7 show_magicians(magician_list)    

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
a
b
c

 

8-10 了不起的魔术师:在你为完成练习8-9而编写的程序中,编写一个名为make_great()的函数,对魔术师列表进行修改,在每个魔术师的名字中都加入字样“the Great”。调用函数show_magicians(),确认魔术师列表确实变了。

 1 magician_list = ['a','b','c']
 2 
 3 def show_magicians(magicians):
 4     for magician in magicians:
 5         print(magician)
 6 
 7 
 8 def make_great(magician_list):
 9     for i in range(0, len(magician_list)):
10         magician_list[i] = "the Great " + magician_list[i]
11 
12         
13 make_great(magician_list) 
14 
15 show_magicians(magician_list) 

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
the Great a
the Great b
the Great c

另一种实现,用到了刚学到的知识:

 1 magician_list = ['a','b','c']
 2 magician_new =[]
 3 
 4 def show_magicians(magicians):
 5     for magician in magicians:
 6         print(magician)
 7 
 8 def make_great(magician_list):
 9     while magician_list:
10         current = "the great " + magician_list.pop()
11         magician_new.append(current)  
12         
13 make_great(magician_list) 
14 
15 show_magicians(magician_new)    

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
the great c
the great b
the great a

 

8-11 不变的魔术师:修改你为完成练习8-10而编写的程序,在调用函数make_great()时,向它传递魔术师列表的副本。由于不想修改原始列表,请返回修改后的列表,并将其存储到另一个列表中。分别使用这两个列表来调用show_magicians(),确认一个列表包含的是原来的魔术师名字,而另一个列表包含的是添加了字样“the Great”的魔术师名字。

 1 magician_list = ['a','b','c']
 2 magician_new =[]
 3 
 4 def show_magicians(magicians):
 5     for magician in magicians:
 6         print(magician)
 7 
 8 def make_great(magician_list):
 9     while magician_list:
10         current = "the great " + magician_list.pop()
11         magician_new.append(current)  
12         
13 make_great(magician_list[:]) 
14 
15 show_magicians(magician_new)
16 show_magicians(magician_list) 
============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
the great c
the great b
the great a
a
b
c

 

动手试一试

8-12 三明治:编写一个函数,它接受顾客要在三明治中添加的一系列食材。这个函数只有一个形参(它收集函数调用中提供的所有食材),并打印一条消息,对顾客点的三明治进行概述。调用这个函数三次,每次都提供不同数量的实参。

1 def food_message(*foods):
2     for food in foods:
3         print(food)
4 
5 food_message("a")
6 print("------------------")
7 food_message('a', "b")
8 print("------------------")
9 food_message("a",'b','c')

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
a
------------------
a
b
------------------
a
b
c

 

8-13 用户简介:复制前面的程序user_profile.py,在其中调用build_profile()来创建有关你的简介;调用这个函数时,指定你的名和姓,以及三个描述你的键-值对。

 1 def build_profile(first, last, **user_info):
 2     """创建一个字典,其中包含我们知道的有关用户的一切"""
 3     profile = {}
 4     profile['first_name'] = first
 5     profile['last_name'] = last
 6     for key, value in user_info.items():
 7         profile[key] = value
 8     return profile
 9 
10 user_profile = build_profile('albert', 'einstein',
11                              location='princeton',
12                              field='physics',
13                              age = 18)
14 
15 print(user_profile)

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics', 'age': 18}

 

8-14 汽车:编写一个函数,将一辆汽车的信息存储在一个字典中。这个函数总是接受制造商和型号,还接受任意数量的关键字实参。这样调用这个函数:提供必不可少的信息,以及两个名称—值对,如颜色和选装配件。这个函数必须能够像下面这样进行调用:

car = make_car('subaru', 'outback', color='blue', tow_package=True)

打印返回的字典,确认正确地处理了所有的信息。

 1 def cars(manufacturer, car_type, **items):
 2     car_info = {}
 3     car_info['manufacturer'] = manufacturer
 4     car_info['car_type'] = car_type
 5     for key,value in items.items():
 6         car_info[key] = value
 7     return car_info
 8 
 9 car_info = cars('BMW',740, color = 'red', displacement='5.2L', number=4)
10 
11 print(car_info)

============== RESTART: C:/ProgramFiles/Python/Python36/test.py ==============
{'manufacturer': 'BMW', 'car_type': 740, 'color': 'red', 'displacement': '5.2L', 'number': 4}

 

动手试一试

8-15 打印模型:将示例print_models.py中的函数放在另一个名为printing_functions.py的文件中;在print_models.py的开头编写一条import语句,并修改这个文件以使用导入的函数。

printing_functions.py

 1 def print_models(unprinted_designs, completed_models):
 2     while unprinted_designs:
 3         current_design = unprinted_designs.pop()
 4 
 5         # 模拟根据设计制作3D打印模型的过程
 6         print("Printing model: " + current_design)
 7         completed_models.append(current_design)
 8 
 9 def show_completed_models(completed_models):
10     """显示打印好的所有模型"""
11     print("\nThe following models have been printed:")
12     for completed_model in completed_models:
13         print(completed_model)

print_models.py

1 import printing_functions
2 
3 # 首先创建一个列表,其中包含一些要打印的设计
4 unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
5 completed_models = []
6 
7 printing_functions.print_models(unprinted_designs, completed_models)
8 
9 printing_functions.show_completed_models(completed_models)

========== RESTART: C:\ProgramFiles\Python\Python36\print_models.py ==========
Printing model: dodecahedron
Printing model: robot pendant
Printing model: iphone case

The following models have been printed:
dodecahedron
robot pendant
iphone case

 

8-16 导入:选择一个你编写的且只包含一个函数的程序,并将这个函数放在另一个文件中。在主程序文件中,使用下述各种方法导入这个函数,再调用它:

import module_name
from module_name import function_name
from module_name import function_name as fn
import module_name as mn
from module_name import *

8-17 函数编写指南:选择你在本章中编写的三个程序,确保它们遵循了本节介绍的函数编写指南。

在本章中,你学习了:如何编写函数,以及如何传递实参,让函数能够访问完成其工作所需的信息;如何使用位置实参和关键字实参,以及如何接受任意数量的实参;显示输出的函数和返回值的函数;如何将函数同列表、字典、if语句和while循环结合起来使用。你还知道了如何将函数存储在被称为模块的独立文件中,让程序文件更简单、更易于理解。最后,你学习了函数编写指南,遵循这些指南可让程序始终结构良好,并对你和其他人来说易于阅读。

程序员的目标之一是,编写简单的代码来完成任务,而函数有助于你实现这样的目标。它们让你编写好代码块并确定其能够正确运行后,就可置之不理。确定函数能够正确地完成其工作后,你就可以接着投身于下一个编码任务。

函数让你编写代码一次后,想重用它们多少次就重用多少次。需要运行函数中的代码时,只需编写一行函数调用代码,就可让函数完成其工作。需要修改函数的行为时,只需修改一个代码块,而所做的修改将影响调用这个函数的每个地方。

使用函数让程序更容易阅读,而良好的函数名概述了程序各个部分的作用。相对于阅读一系列的代码块,阅读一系列函数调用让你能够更快地明白程序的作用。

函数还让代码更容易测试和调试。如果程序使用一系列的函数来完成其任务,而其中的每个函数都完成一项具体的工作,测试和维护起来将容易得多:你可编写分别调用每个函数的程序,并测试每个函数是否在它可能遇到的各种情形下都能正确地运行。经过这样的测试后你就能信心满满,深信你每次调用这些函数时,它们都将正确地运行。

在第9章,你将学习编写类。类将函数和数据整洁地封装起来,让你能够灵活而高效地使用它们。


 第 9 章 类

动手试一试

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

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

 1 class Restaurant():
 2     
 3     def __init__(self,restaurant_name, cuisine_type):
 4         self.restaurant_name = restaurant_name
 5         self.cuisine_type = cuisine_type
 6     
 7     def describe_restaurant(self):
 8         print(f"restaurant name is {self.restaurant_name}")
 9         print(f"cuisine type is {self.cuisine_type}")
10            
11     def open_restaurant(self):
12         print("Open")
13 
14 restaurant = Restaurant("chuancai", "hot pot")
15 
16 restaurant.describe_restaurant()
17 restaurant.open_restaurant()

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
restaurant name is chuancai
cuisine type is hot pot
Open

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

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

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

 1 class User():
 2     def __init__(self, first_name, last_name):
 3         self.first_name = first_name
 4         self.last_name = last_name
 5 
 6     def describe_user(self):
 7         print(f"username is: " + self.first_name + " "+ self.last_name)
 8 
 9     def greet_user(self):
10         print("hello, {}! ".format(self.last_name))
11 
12 user_1 = User("John","Smith")
13 user_1.describe_user()
14 user_1.greet_user()
15 
16 user_2 =User("xiao", "ming")
17 user_2.describe_user()
18 user_2.greet_user()   

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
username is: John Smith
hello, Smith!
username is: xiao ming
hello, ming!

 

动手试一试

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

添加一个名为set_number_served()的方法,它让你能够设置就餐人数。调用这个方法并向它传递一个值,然后再次打印这个值。

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

 

 1 class Restaurant():
 2 
 3     def __init__(self,restaurant_name, cuisine_type):
 4         self.restaurant_name = restaurant_name
 5         self.cuisine_type = cuisine_type
 6         self.number_served = 0
 7 
 8     def describe_restaurant(self):
 9         print(f"restaurant name is {self.restaurant_name}")
10         print(f"cuisine type is {self.cuisine_type}")
11 
12     def open_restaurant(self):
13         print("Open")
14 
15     def set_number_served(self, number):
16         self.number_served = number
17         print(f"{self.number_served} person has served!")
18 
19     def increment_number_served(self, numbers):
20         self.number_served += numbers
21         print(f"{self.number_served} person has served!")
22 
23 restaurant = Restaurant("chuancai", "hot pot")
24 restaurant.set_number_served(10)
25 restaurant.increment_number_served(20)
26 restaurant.increment_number_served(30)

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
10 person has served!
30 person has served!
60 person has 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 class User():
 2     def __init__(self, first_name, last_name):
 3         self.first_name = first_name
 4         self.last_name = last_name
 5         self.login_attempts = 0
 6 
 7     def increment_login_attempts(self):
 8         self.login_attempts += 1
 9 
10     def reset_login_attempts(self):
11         self.login_attempts = 0
12     
13 user_1 = User("John","Smith")
14 user_1.increment_login_attempts()
15 user_1.increment_login_attempts()
16 user_1.increment_login_attempts()
17 print(user_1.login_attempts)
18 
19 user_1.reset_login_attempts()
20 print(user_1.login_attempts)

0============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
3
0

 

动手试一试

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

 1 class Restaurant():
 2 
 3     def __init__(self,restaurant_name, cuisine_type):
 4         self.restaurant_name = restaurant_name
 5         self.cuisine_type = cuisine_type
 6 
 7     def describe_restaurant(self):
 8         print(f"restaurant name is {self.restaurant_name}")
 9         print(f"cuisine type is {self.cuisine_type}")
10 
11     def open_restaurant(self):
12         print("Open")
13 
14 class IceCreamStand(Restaurant):
15     def __init__(self, restaurant_name, cuisine_type):
16         super().__init__(restaurant_name, cuisine_type)
17         self.flavors = []
18 
19     def show_icecream(self):
20         for flavor in self.flavors:
21             print(flavor)
22 
23 icecream = IceCreamStand("haagen-Dazs", "icecream")
24 icecream.flavors = ["a", "b", "c"]
25 
26 icecream.show_icecream()

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
a
b
c

 

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

 1 class User():
 2     def __init__(self, first_name, last_name):
 3         self.first_name = first_name
 4         self.last_name = last_name
 5 
 6     def describe_user(self):
 7         print(f"username is: " + self.first_name + " "+ self.last_name)
 8 
 9     def greet_user(self):
10         print("hello, {}! ".format(self.last_name))
11 
12 class Admin(User):
13     def __init__(self, first_name, last_name):
14         super().__init__(first_name, last_name)
15         self.privileges =["can add post", "can delete post", "can ban user"]
16 
17     def show_privileges(self):
18         for privilege in self.privileges:
19             print(privilege)
20 
21 admin = Admin("John", "Smith")
22 
23 admin.show_privileges()

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
can add post
can delete post
can ban user

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

 1 class User():
 2     def __init__(self, first_name, last_name):
 3         self.first_name = first_name
 4         self.last_name = last_name
 5 
 6     def describe_user(self):
 7         print(f"username is: " + self.first_name + " "+ self.last_name)
 8 
 9     def greet_user(self):
10         print("hello, {}! ".format(self.last_name))
11 
12 
13 class Privileges():    
14     def __init__(self):
15         self.privileges =["can add post", "can delete post", "can ban user"]
16 
17     def show_privileges(self):
18         for privilege in self.privileges:
19             print(privilege)   
20 
21 class Admin(User):
22     def __init__(self, first_name, last_name):
23         super().__init__(first_name, last_name)
24         self.privilege = Privileges()
25 
26     def show_privileges(self):
27         self.privilege.show_privileges()
28 
29 admin = Admin("John", "Smith")
30 
31 admin.show_privileges()

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
can add post
can delete post
can ban user

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

 1 class Car():
 2     def __init__(self, make, model, year):
 3         self.make = make
 4         self.model = model
 5         self.year = year
 6         self.odometer_reading = 0
 7 
 8     def get_descriptive_name(self):
 9         long_name = str(self.year) + ' ' + self.make + ' ' + self.model
10         return long_name.title()
11 
12 class Battery():
13     """一次模拟电动汽车电瓶的简单尝试"""
14 
15     def __init__(self, battery_size=60):
16         """初始化电瓶的属性"""
17         self.battery_size = battery_size
18         
19     def describe_battery(self):
20         """打印一条描述电瓶容量的消息"""
21         print("This car has a " + str(self.battery_size) + "-kWh battery.")
22 
23     def get_range(self):
24         """Print a statement about the range this battery provides.""" 
25         if self.battery_size == 60:
26             range1 = 140
27         elif self.battery_size == 85:
28             range1 = 185
29             
30         message = "This car can go approximately " + str(range1)
31         message += " miles on a full charge."
32         print(message)
33 
34     def upgrade_battery(self):
35         self.battery_size = 85
36 
37 class ElectricCar(Car):
38 
39     def __init__(self, manufacturer, model, year):
40         """
41         Initialize attributes of the parent class.
42         Then initialize attributes specific to an electric car.
43         """
44         super().__init__(manufacturer, model, year)
45         self.battery = Battery()
46 
47 
48 my_tesla = ElectricCar('tesla', 'model s', 2016)
49 my_tesla.battery.get_range()
50 my_tesla.battery.upgrade_battery()
51 my_tesla.battery.get_range()

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
This car can go approximately 140 miles on a full charge.
This car can go approximately 185 miles on a full charge.

 

动手试一试

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

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

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

 

动手试一试

9-13 使用OrderedDict:在练习6-4中,你使用了一个标准字典来表示词汇表。请使用OrderedDict类来重写这个程序,并确认输出的顺序与你在字典中添加键—值对的顺序一致。

 1 from collections import OrderedDict
 2 
 3 dicts = {'list': '列表', 'str': '字符串', 'tuple': '元组', 'dict': '字典', 'int': '整型' }
 4 
 5 dicts['split'] = '切片'
 6 dicts['if'] =  '条件'
 7 dicts['class'] = ''
 8 dicts['object'] = '对象'
 9 dicts['boolean'] = '布尔'
10 
11 order_dicts = OrderedDict()
12 for key, value in dicts.items():
13     order_dicts[key] = value
14 
15 for key, value in order_dicts.items():
16     print(f"{key} : {value}")

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
list : 列表
str : 字符串
tuple : 元组
dict : 字典
int : 整型
split : 切片
if : 条件
class : 类
object : 对象
boolean : 布尔

9-14 骰子:模块random包含以各种方式生成随机数的函数,其中的randint()返回一个位于指定范围内的整数,例如,下面的代码返回一个1~6内的整数:

from random import randint
x = randint(1, 6)

请创建一个Die类,它包含一个名为sides的属性,该属性的默认值为6。编写一个名为roll_die()的方法,它打印位于1和骰子面数之间的随机数。创建一个6面的骰子,再掷10次。 创建一个10面的骰子和一个20面的骰子,并将它们都掷10次。

 1 from random import randint
 2 
 3 class Die():
 4     def __init__(self, sides=6):
 5         self.sides = sides     
 6 
 7     def roll_die(self):
 8         x = randint(1, self.sides)
 9         print(x, end=" ")
10 
11 print("\n-----------6------------")  
12 dice_6 = Die()
13 
14 i = 0
15 while i < 10:
16     dice_6.roll_die()
17     i = i + 1
18 
19 print("\n-----------10------------")        
20 dice_10 = Die(10)        
21         
22 i = 0
23 while i < 10:
24     dice_6.roll_die()
25     i = i + 1
26 
27     dice_10 = Die(10)        
28 
29 print("\n-----------20------------")
30 dice_6 = Die(20)
31 i = 0
32 while i < 10:
33     dice_6.roll_die()
34     i = i + 1

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============

-----------6------------
4 4 1 1 2 2 6 3 5 3
-----------10------------
5 4 4 3 2 6 4 2 1 2
-----------20------------
8 8 3 13 20 17 5 4 16 11

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

你必须熟悉有些与类相关的编码风格问题,在你编写的程序较复杂时尤其如此。

类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。

对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。

可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。

需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import语句,再添加一个空行,然后编写导入你自己编写的模块的import语句。在包含多条import语句的程序中,这种做法让人更容易明白程序使用的各个模块都来自何方。

在本章中,你学习了:如何编写类;如何使用属性在类中存储信息,以及如何编写方法,以让类具备所需的行为;如何编写方法__init__(),以便根据类创建包含所需属性的实例。你见识了如何修改实例的属性——包括直接修改以及通过方法进行修改。你还了解了:使用继承可简化相关类的创建工作;将一个类的实例用作另一个类的属性可让类更简洁。

你了解到,通过将类存储在模块中,并在需要使用这些类的文件中导入它们,可让项目组织有序。你学习了Python标准库,并见识了一个使用模块collections中的OrderedDict类的示例。最后,你学习了编写类时应遵循的Python约定。

在第10章中,你将学习如何使用文件,这让你能够保存你在程序中所做的工作,以及你让用户做的工作。你还将学习异常,这是一种特殊的Python类,用于帮助你在发生错误时采取相应的措施。


 第 10 章 文件和异常

动手试一试

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

 1 print("\n----------------1-----------------")
 2 with open("learning_python.txt") as fbj:
 3     content = fbj.read().rstrip()
 4     print(content) 
 5 
 6 print("\n----------------2-----------------")
 7 with open("learning_python.txt") as fbj:
 8     for line in fbj:
 9         print(line.rstrip())
10 
11 print("\n----------------3-----------------")
12 with open("learning_python.txt") as fbj:
13     lines = fbj.readlines()
14 
15 for line in lines:
16     print(line.rstrip())

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============

----------------1-----------------
In Python you can sing
In Python you can cry
In Python you can dance

----------------2-----------------
In Python you can sing
In Python you can cry
In Python you can dance

----------------3-----------------
In Python you can sing
In Python you can cry
In Python you can dance

10-2 C语言学习笔记:可使用方法replace()将字符串中的特定单词都替换为另一个单词。下面是一个简单的示例,演示了如何将句子中的'dog'替换为'cat'

>>> message = "I really like dogs."
>>> message.replace('dog', 'cat')
'I really like cats.'

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

1 with open("learning_python.txt") as fbj:
2     lines = fbj.readlines()
3 
4 for line in lines:
5     re_line = line.replace("Python", "c")
6     print(re_line)

============== RESTART: C:\ProgramFiles\Python\Python36\test.py ==============
In c you can sing
In c you can cry
In c you can dance

动手试一试

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

1 with open("guest.txt", 'w') as fbj:
2     txt = input("enter your username: > ")
3     fbj.write(txt)  

 

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

 1 while True:
 2     prompt = "please enter your name:"
 3     prompt += "\n(enter 'q' when you quit) > "
 4     text = input(prompt)    
 5     if text =='q':
 6         break
 7     greet = "welcome: " + text + " !\n"
 8     print(greet)
 9     with open("guest_book.txt", "a") as fbj:
10         fbj.write(greet)

 

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

1 while True:
2     prompt = "why?!"
3     prompt += "\n(enter 'q' when you quit) > "
4     text = input(prompt)    
5     if text =='q':
6         break
7     with open("guest_book.txt", "a") as fbj:
8         fbj.write(text + "\n")

 

动手试一试

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

1 try:
2     number_1 = int(input("first number: > "))
3     number_2 = int(input("second number: > "))
4 except ValueError:
5     print("please enter the number")
6 else:
7     print(number_1 + number_2)

 

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

1 while True:
2     try:
3         number_1 = int(input("first number: > "))
4         number_2 = int(input("second number: > "))
5     except ValueError:
6         print("please enter a number!")
7     else:
8         print(number_1 + number_2)
9         break

 

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

1 try:
2     with open("cat.txt") as fbj_1:
3         print(fbj_1.read())
4     with open("dog.txt") as fbj_2:
5         print(fbj_2.read())
6 except FileNotFoundError:
7     print("file not found!")

 

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

1 try:
2     with open("cat.txt") as fbj_1:
3         print(fbj_1.read())
4     with open("dog.txt") as fbj_2:
5         print(fbj_2.read())
6 except FileNotFoundError:
7     pass

 

10-10 常见单词:访问项目Gutenberg(http://gutenberg.org/),并找一些你想分析的图书。下载这些作品的文本文件或将浏览器中的原始文本复制到文本文件中。

你可以使用方法count()来确定特定的单词或短语在字符串中出现了多少次。例如,下面的代码计算'row'在一个字符串中出现了多少次:

>>> line = "Row, row, row your boat"
>>> line.count('row')
7+/*2
>>> line.lower().count('row')
3

请注意,通过使用lower()将字符串转换为小写,可捕捉要查找的单词出现的所有次数,而不管其大小写格式如何。

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

1 with open("test.txt") as fbj:
2     contents = fbj.read()
3     numbers = contents.lower().count("the")
4     print(numbers) 

 

动手试一试

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

1 import json
2 
3 filename = "number.json"
4 with open(filename, 'w') as fbj:
5     number = input("enter you favorite number: > ")
6     json.dump(number, fbj)
7 with open(filename, 'r') as fbj:
8     number = json.load(fbj)
9     print("I know your favorite number! It's " + number)

 

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

 1 import json
 2 
 3 filename = "number.json"
 4 
 5 try:
 6     with open(filename) as fbj:
 7         number = json.load(fbj)
 8 except FileNotFoundError:
 9     number = input("enter you favorite number: > ")
10     print("your favorite number is: " + number)
11     with open(filename, 'w') as fbj:        
12         json.dump(number, fbj)    
13 else:
14      print("I know your favorite number! It's " + number)

 

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

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

 1 import json
 2 
 3 def get_stored_username():
 4     """Get stored username if available."""
 5     filename = 'username.json'
 6     try:
 7         with open(filename) as f_obj:
 8             username = json.load(f_obj)
 9     except FileNotFoundError:
10         return None
11     else:
12         return username
13 
14 def get_new_username():
15     """Prompt for a new username."""
16     username = input("What is your name? ")
17     filename = 'username.json'
18     with open(filename, 'w') as f_obj:
19         json.dump(username, f_obj)
20     return username
21 
22 def greet_user():
23     """Greet the user by name."""
24     username = get_stored_username()   
25     if username:
26         flag = input(f"your name is {username},yes or no? > ")
27         if flag == "yes":
28             print("Welcome back, " + username + "!")
29         elif flag == "no":
30             username = get_new_username()
31             print("We'll remember you when you come back, " + username + "!")
32         else:
33             print("input error!")        
34     else:
35         username = get_new_username()
36         print("We'll remember you when you come back, " + username + "!")
37 
38 greet_user()

 

在本章中,你学习了:如何使用文件;如何一次性读取整个文件,以及如何以每次一行的方式读取文件的内容;如何写入文件,以及如何将文本附加到文件末尾;什么是异常以及如何处理程序可能引发的异常;如何存储Python数据结构,以保存用户提供的信息,避免用户每次运行程序时都需要重新提供。

在第11章中,你将学习高效的代码测试方式,这可帮助你确定代码正确无误,以及发现扩展现有程序时可能引入的bug。


 第 11 章 测试代码

动手试一试

11-1 城市和国家:编写一个函数,它接受两个形参:一个城市名和一个国家名。这个函数返回一个格式为City, Country的字符串,如Santiago, Chile。将这个函数存储在一个名为city_functions.py的模块中。

创建一个名为test_cities.py的程序,对刚编写的函数进行测试(别忘了,你需要导入模块unittest以及要测试的函数)。编写一个名为test_city_country()的方法,核实使用类似于'santiago''chile'这样的值来调用前述函数时,得到的字符串是正确的。运行test_cities.py,确认测试test_city_country()通过了。

 1 import unittest
 2 
 3 def country_city(city, country):
 4     return (city + ", " + country).title()
 5 
 6 class CityTestCases(unittest.TestCase):
 7     def test_city_country(self):
 8         self.assertEqual(country_city("Santiago", "Chile"), "Santiago, Chile")
 9 
10 unittest.main()

 

11-2 人口数量:修改前面的函数,使其包含第三个必不可少的形参population,并返回一个格式为City, Country - population xxx的字符串,如Santiago, Chile - population 5000000。运行test_cities.py,确认测试test_city_country()未通过。

修改上述函数,将形参population设置为可选的。再次运行test_cities.py,确认测试test_city_country()又通过了。

再编写一个名为test_city_country_population()的测试,核实可以使用类似于'santiago''chile''population=5000000'这样的值来调用这个函数。再次运行test_cities.py,确认测试test_city_country_population()通过了。

 1 import unittest
 2 
 3 def country_city(city, country, population=""):
 4     if population:
 5         info = city.title() + ", " + country.title() + " - population " + str(population)
 6     else:
 7         info = city.title() + ", " +  country.title()
 8     return (info)
 9 
10 class CityTestCases(unittest.TestCase):
11     def test_city_country(self):
12         self.assertEqual(country_city("Santiago", "Chile"), "Santiago, Chile")
13 
14     def test_city_country_population(self):
15         self.assertEqual(country_city("Santiago", "Chile", 10000), "Santiago, Chile - population 10000")
16 
17 unittest.main()

 

动手试一试

11-3 雇员:编写一个名为Employee的类,其方法__init__()接受名、姓和年薪,并将它们都存储在属性中。编写一个名为give_raise()的方法,它默认将年薪增加5000美元,但也能够接受其他的年薪增加量。

Employee编写一个测试用例,其中包含两个测试方法:test_give_default_raise()test_give_custom_raise()。使用方法setUp(),以免在每个测试方法中都创建新的雇员实例。运行这个测试用例,确认两个测试都通过了。

 1 import unittest
 2 
 3 class Employee():
 4     def __init__(self, first, last, money):
 5         self.first = first
 6         self.last = last
 7         self.money = money
 8 
 9     def give_raise(self, increase = 50):
10         self.money += increase
11         return self.money
12 
13 class EmployeeTestCase(unittest.TestCase):
14     def setUp(self):
15         self.employee = Employee("john", "smith", 1000)
16 
17     def test_give_default_raise(self):
18         self.employee.give_raise()
19         self.assertEqual(self.employee.money, 1050)
20 
21     def test_give_custom_raise(self):
22         self.employee.give_raise(100)
23         self.assertEqual(self.employee.money, 1100)
24 
25 unittest.main()

 

在本章中,你学习了:如何使用模块unittest中的工具来为函数和类编写测试;如何编写继承unittest.TestCase的类,以及如何编写测试方法,以核实函数和类的行为符合预期;如何使用方法setUp()来根据类高效地创建实例并设置其属性,以便在类的所有测试方法中都可使用它们。

测试是很多初学者都不熟悉的主题。作为初学者,并非必须为你尝试的所有项目编写测试;但参与工作量较大的项目时,你应对自己编写的函数和类的重要行为进行测试。这样你就能够更加确定自己所做的工作不会破坏项目的其他部分,你就能够随心所欲地改进既有代码了。如果不小心破坏了原来的功能,你马上就会知道,从而能够轻松地修复问题。相比于等到不满意的用户报告bug后再采取措施,在测试未通过时采取措施要容易得多。

如果你在项目中包含了初步测试,其他程序员将更敬佩你,他们将能够更得心应手地尝试使用你编写的代码,也更愿意与你合作开发项目。如果你要跟其他程序员开发的项目共享代码,就必须证明你编写的代码通过了既有测试,通常还需要为你添加的新行为编写测试。

请通过多开展测试来熟悉代码测试过程。对于自己编写的函数和类,请编写针对其重要行为的测试,但在项目早期,不要试图去编写全覆盖的测试用例,除非有充分的理由这样做。

 

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

posted @ 2020-08-10 19:18  信德维拉  阅读(27007)  评论(0编辑  收藏  举报