《Think Python》课后实现合集
这是什么?
你好!这里是九月初夏的 《Think Python》作业本 !在这里我将记录自己《Think Python》的章节练习和解题思路,希望能和你一起度过奇妙的编程初见之旅~ 为了便于寻找和我自己区分,我给每个习题都取了个名字。
- 这是《Think Python》哪个版本的作业?
《Think Python:如何像计算机科学家一样思考》第二版(基于Python 3),各大购书平台有售。当然便于写作业的时候“誊抄”题目,我找到了一本双语PDF(作者让这本书基于GNU自由文档许可协议“开源”了,但是该版本部分习题和纸书不同),来自哈尔滨工业大学 车万翔教授 ,渠道是中国大学MOOC。
- 可以当成《Think Python》参考答案吗?
参考答案建议还是以 绿茶出版社官方代码 为准。这里主要存放的还是我的个人答案和解题感悟,当然因为是编程初见,很有可能出现 无法求解 的情况,你有可能看到的是无法正确实现题目要求的代码。当然,如果发生这种情况我会再放一份官方代码研究,并 分析原因、总结规律 ,当然希望这种情况不要发生_(:зゝ∠)_ 还有就是一些没有官方答案的题目,我也不能保证100%正确_(:зゝ∠)_
课堂笔记&课后作业
第1章 程序之道
练习 1-1:在交互模式中故意犯错(1)
【习题 1.1.1】 在 print
语句中,如果漏掉一个括号,或者两个都漏掉,会发生什么?
【求解】
情况1:漏掉左括号,或者都漏掉
>>> print 'Holle, World!')
File "<stdin>", line 1
print 'Holle, World!')
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print('Holle, World!'))?
>>>print 'Holle, World!'
File "<stdin>", line 1
print 'Holle, World!')
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print('Holle, World!'))?
序号 | 报错 | 含义 |
---|---|---|
1 | SyntaxError: Missing parentheses in call to ‘print’. | 语法错误:调用时缺少括号 |
推测原因:Python 2 中 print
语句不需要括号,而Python 3 需要,所以这里特别说明缺少括号并给出了可能的建议
情况2:漏掉右括号
>>>print ('Holle, World!'
^
SyntaxError: unexpected EOF while parsing
序号 | 报错 | 含义 |
---|---|---|
2 | SyntaxError: unexpected EOF while parsing | 语法错误:解析时意外终止 |
推测原因:解释器从左往右读代码, print
语句没有终止符,后面又没有东西,就“意外终止”了
【习题 1.1.2】 如果正尝试打印一个字符串,那么漏掉一个货所有引号,会发生什么?
【求解】
情况1:漏掉左引号,或者都漏掉
>>>print (Holle, World!')
File "<stdin>", line 1
print (Holle, World!')
^
SyntaxError: invalid syntax
>>>print (Holle, World!)
File "<stdin>", line 1
print (Holle, World!)
^
SyntaxError: invalid syntax
序号 | 报错 | 含义 |
---|---|---|
3 | SyntaxError: invalid syntax | 语法错误:无效语法 |
推测原因:没有引号,解释器将括号里的“Holle, World!”当成了一个变量名,但是逗号、空格、感叹号是非法字符,违背了变量命名的规则,去掉这些符号后,报错就变成了“命名错误:命名没有被定义”了
>>>print ('HolleWorld')
Traceback (most recent call last):
File "<stdin>", line 1
print (HolleWorld)
NameError: name 'HolleWorld' is not defined
序号 | 报错 | 含义 |
---|---|---|
5 | NameError: name ‘HolleWorld’ is not defined | 命名错误:命名没有被定义 |
情况2:漏掉右引号
>>>print ('Holle, World!)
File "<stdin>", line 1
print ('Holle, World!)
^
SyntaxError: EOL while scanning string literal
序号 | 报错 | 含义 |
---|---|---|
4 | SyntaxError: EOL while scanning string literal | 语法错误:扫描字符串时行终止 |
推测原因:解释器从左往右读代码,字符串没有终止符,但是print
语句却终止了,故“扫描字符串时行终止”
【习题 1.1.3】 可以使用一个负号来表示负数,如-2。如果在数字之前放一个正好,会发生什么?如果是2++2呢?
【求解】
>>> -2
-2
>>> 2++2
4
【习题 1.1.4】 在数学标记里,前置 0 是没有问题的,如 02。在 Python 中也这么做会发生什么?
【求解】
>>> 02
2
【习题 1.1.5】 如果在两个值之间不放任何操作符,会发生什么?
【求解】
情况1:两个值中间无空格:
>>> 24
24
情况2:两个值中间有空格:
>>> 2 4
File "<stdin>", line 1
2 4
^
SyntaxError: invalid syntax
序号 | 报错 | 含义 |
---|---|---|
3 | SyntaxError: invalid syntax | 语法错误:无效语法 |
练习 1-2:解释器牌计算器(时间换算、距离换算、速度换算)
【习题 1.2.1】 在42分42秒钟,一共有多少秒?
【求解】
>>> 42*60+42
2562
【习题 1.2.2】 10千米相当于多少英里?提示:1英里相当于1.61千米。
【求解】
>>> 10/1.61
6.211180124223602
【习题 1.2.3】 如果你42分42秒跑完10千米,那么你的平均速度(跑1千米需要的分钟和秒数)是多少?平均速度是多少千米每小时?
【求解】
问题1:跑1千米需要的分钟和秒数:
分钟:
>>> (42*60+42)/10/60
4
秒数:
>>> (42*60+42)/10.0%60
16.19999999999999
问题2:平均速度是多少千米每小时:
>>> 10.0/(42*60+42)*60*60
14.051522248243561
第2章 变量、表达式和语句
练习 2-1:在交互模式中故意犯错(2)
【习题 2.1.1】 我们已经见过 n = 42 是合法的。那么 42 = n 呢?
【求解】
>>> 42 = n
File "<stdin>", line 1
SyntaxError: can't assign to literal
序号 | 报错 | 含义 |
---|---|---|
6 | SyntaxError: can’t assign to literal | 语法错误:不能给文字赋值 |
【习题 2.1.2】 那么 x = y = 1呢?
【求解】
>>> x = y = 1
>>> x
1
>>> y
1
【习题 2.1.3】 有些语言中,每个语句都需要以分好(;)结尾。如果你在 Python 语句的结尾放一个分好,会有什么情况?
【求解】
>> x = y = 1
>>> print(x);print(y)
1
1
【习题 2.1.4】 如果在语句结尾放的是句号呢?
【求解】
>>> print(x).
File "<stdin>", line 1
print(x).
^
SyntaxError: invalid syntax
序号 | 报错 | 含义 |
---|---|---|
3 | SyntaxError: invalid syntax | 语法错误:无效语法 |
【习题 2.1.5】 在数学标记中,对于 x 乘以 y,可以这么表达:xy。在Python中这样尝试会有什么结果?
【求解】
>>> x = 2
>>> y = 4
>>> xy
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xy' is not defined
序号 | 报错 | 含义 |
---|---|---|
5 | NameError: name ‘HolleWorld’ is not defined | 命名错误:命名没有被定义 |
练习 2-2:解释器牌计算器(球体积、书总价、晨练到家时间)
【习题 2.2.1】 半径为 r r r 的球体的体积是 ( 4 / 3 ) π r 3 (4/3)πr^{3} (4/3)πr3。半径为 5 5 5 的球体体积是多少?
【求解】
>>> (4.0/3)*3.14*5**3
523.3333333333334
【习题 2.2.2】 假设一本书的定价是24.95美元,但是书店打了40%的折扣(6折)。运费是一本3美元,每加一本加75美分。60本书的总价是多少?
【求解】
>>> 24.95*(1-0.4)*60+3+0.75*(60-1)
945.4499999999999
【习题 2.2.3】 如果我 06:52 时离开家,并以慢速(6分10秒/千米)跑1.6千米,接下来以4分30秒/千米的速度跑4.8千米,再以慢速跑1.6千米。请问我回家吃早餐时什么时候?
【求解】
时:
>> 6+1
7
分:
>>> (52+((6*60+10)*1.6*2+(4*60+30)*4.8-((6*60+10)*1.6*2+(4*60+30)*4.8)%60)/60)%60
33.0
秒:
>>> 0+((6*60+10)*1.6*2+(4*60+30)*4.8)%60
20.0
第3章 函数
练习 3-1:输入长度<70的任意字符串,让其最后一个字母在第70列上
【习题 3.1.1】 编写一个函数 right_justify,接收一个字符串形参 s,并打印出足够的前导空白,以达到最后一个字符显示在第70列上。
>>> right_justify('monty')
monty
提示:可以利用字符串的拼接和重复特性。另外,Python提供了一个内置名为 len
的函数,返回一个字符串的长度,所以 len(‘allen’) 的值是5。
【求解】
先计算s的长度l,前导空白=空格*(70-l):
>>> def right_justify(s):
... l = len(s)
... print(' '*(70-l)+s)
...
>>> right_justify('monty')
monty
将len(s)带入l,还能更剪短点:
>>> def right_justify(s):
... print(' '*(70-len(s))+s)
...
>>> right_justify('monty')
monty
练习 3-2:在函数中调用另一个函数
函数对象是一个值,可以将它赋值给变量,或者作为实参传递。例如,do_twice 是一个函数,接收一个函数对象作为实参,并调用它两次:
def do_twice(f):
f()
f()
下面是一个使用 do_twice 来调用一个 print_spam 函数两次的示例:
def print_spam():
print('spam')
do_twice(print_spam)
【习题 3.2.1】 将这个示例存入脚本并测试它。
【求解】
代码:
def do_twice(f):
f()
f()
def print_spam():
print('spam')
do_twice(print_spam)
运行结果:
spam
spam
【习题 3.2.2】 修改 do_twice,让他接收两个实参,一个是函数对象,另一个是一个值,它会调用函数对象两次,并传入那个值作为实参。
【求解】 这让我想起了代数 y=g(f(x),x)
代码:
def do_twice(f,x):
f(x)
f(x)
def print_spam(x):
print(x)
do_twice(print_spam,'spam')
运行结果:
spam
spam
【习题 3.2.3】 将本章前面介绍的函数 print_twice 的定义复制到你的脚本中。
【求解】
def print_twice(bruce):
print(bruce)
print(bruce)
【习题 3.2.4】 使用修改版的 do_twice 来调用 print_twice 两次,并传入实参 ‘spam’。
【求解】
代码:
def do_twice(f,x):
f(x)
f(x)
def print_twice(bruce):
print(bruce)
print(bruce)
do_twice(print_twice,'spam')
运行结果:
spam
spam
spam
spam
【习题 3.2.4】 定义一个新的函数 do_four,接收一个函数对象与一个值,使用这个值作为实参调用函数4次。这个函数的函数体应该只有2条语句,而不是4条。
【求解】 在 do_four 里调用 do_twice 两次,从而实现调用实参函数4次(2×2)
代码:
#执行函数f(x)两次
def do_twice(f,x):
f(x)
f(x)
#通过执行do_twice(f,x)两次,实现执行f(x)四次
def do_four(f,x):
do_twice(f,x)
do_twice(f,x)
#定义最终被调用的函数
def print_spam(x):
print(x)
#执行将'spam'打印四次
do_four(print_spam,'spam')
执行结果:
spam
spam
spam
spam
练习 3-3:用函数画表格
注意:这个练习应该仅使用当前我们学过的语句和特性来实现。
【习题 3.3.1】 编写一个函数,绘制如下表格:
提示:要在同一行打印出个值,可以使用逗号分隔不同的值:
print ('+', '-')
如果一个序列以逗号结尾,Python会认为这一行没有结束, 于是下一个打印出的值会
出现在同一行。
print ('+', end=' ')
print ('-')
这两条语句的输出结果是’+ -’。
一条单独的print语句会结束当前行,开始下一行。
【分析】
第一步:先分析表格下表格
第二布:确认下方案
首先,题目给出的 print
语句的用法肯定是有用的
print ('+', end=' ')
print ('-')
其次,【习题 3.2.4】 的 do_twice 和 do_four 也是有用的
#执行函数f(x)两次
def do_twice(f,x):
f(x)
f(x)
#通过执行do_twice(f,x)两次,实现执行f(x)四次
def do_four(f,x):
do_twice(f,x)
do_twice(f,x)
所以我打算用 do_twice 画边界和空白的每一条,再用 do_four 画4条空白的行高
【求解】
#执行函数f(x)两次
def do_twice(f,x,y):
f(x,y)
f(x,y)
#通过执行do_twice(f,x)两次,实现执行f(x)四次
def do_four(f,x,y):
do_twice(f,x,y)
do_twice(f,x,y)
#画出表格的每条,边界、空白可用
def do(x,y):
print (x, end=' ')
print (x, end=' ')
print (y)
#画出表格的“一行”:1条上边+4条行高
def line():
do('+ - - - -','+')
do_four(do,'| ','|')
#画出表格:2行+1底边
def list():
line()
line()
do('+ - - - -','+')
list()
【再解】 瞄了一眼,下面 【习题 3.3.1】 要求变成 4 × 4 的表格,我想能不能把变量尽量提出来,改变表格的时候改个数字就好了?最后发现列很容易做到(用《Think Python》13页《2.6 字符串操作》中的 ‘Spam’*3),行还是要靠 print
语句一行一行打印。
当然此方法中的“+ - - - - ”和“| ”要比 【求解】 中多1个空格
#变量:表格列数
n = 2
#n列表格的1条:n个循环体+1个终止符,边界、空白均可使用
def cell(x,y,n):
print(x*n+y)
#行高:4条空白(直接4条,懒得再定义do_twice和do_four了)
def line_height_4(n):
cell('| ','|',n)
cell('| ','|',n)
cell('| ','|',n)
cell('| ','|',n)
#行:一条边界+行高
def line(n):
cell('+ - - - - ','+',n)
line_height_4(n)
#表格:2行+1底
def list(n):
line(n)
line(n)
cell('+ - - - - ','+',n)
#执行表格函数,打印出表格
list(n)
【习题 3.3.2】 编写一个函数绘制类似的表格,单有4行4列。
【求解】 基于 【习题 3.3.1】 中的 【求解】,用了 do_twice 和 do_four,没有被拿出来的变量。
代码变动:需要在画“每条”时多打印“列” print (x, end=’ ') 2次,画表格的时候多打印“行” line() 2次
#执行函数f(x)两次
def do_twice(f,x,y):
f(x,y)
f(x,y)
#通过执行do_twice(f,x)两次,实现执行f(x)四次
def do_four(f,x,y):
do_twice(f,x,y)
do_twice(f,x,y)
#画出表格的每条,边界、空白可用
def do(x,y):
print (x, end=' ')
print (x, end=' ')
print (x, end=' ')
print (x, end=' ')
print (y)
#画出表格的“一行”:1条上边+4条行高
def line():
do('+ - - - -','+')
do_four(do,'| ','|')
#画出表格:2行+1底边
def list():
line()
line()
line()
line()
do('+ - - - -','+')
list()
【再解】 基于 【习题 3.3.1】 中的