《Python程序设计(第3版)》[美] 约翰·策勒(John Zelle) 第 5 章 答案

《Python程序设计(第3版)》[美] 约翰·策勒(John Zelle) 第 5 章 答案

答案仅供参考,若有错误欢迎指正

判断对错

  1. Python 字符串字面量总是用双引号括起来。
  2. 字符串 s 的最后一个字符在位置 len(s)−1。
  3. 一个字符串总是包含一行文本。
  4. 在 Python 中,“4” + “5"是"45”。
  5. Python 列表是可变的,但字符串不是。
  6. ASCII 是使用数字代码表示字符的标准。
  7. split 方法将一个字符串拆分为一个子字符串列表,而 join 则相反。
  8. 替换加密是保持敏感信息安全的好方法。
  9. 可以用 add 方法在列表末尾添加一项。
  10. 将文件与程序中的对象相关联的过程称为“读取”该文件。

解答

  1. F(p.81 “在第 2 章中你已了解到,通过用引号将一些字符括起来形成字符串字面量。Python 还允许字符串由单引号(撇号)分隔。它们没有区别,但用时一定要配对。”)
  2. T(p.82 “请注意,在 n 个字符的字符串中,最后一个字符位于位置 n-1,因为索引从 0 开始。”)
  3. F(字符串是一个字符序列,该序列可以是任意长度的,所以该序列也可以是一个空字符串)
  4. T(4 和 5 都被引号括起来了,所以是字符串类型,而不是整数类型,“+”表示连接这两个字符串。)
  5. T(p.87 “虽然字符串和列表都是序列,但两者之间有一个重要的区别。列表是可变的。这意味着列表中项的值可以使用赋值语句修改。另一方面,字符串不能在“适当位置“改变。”)
  6. T(p.88 “为了避免这种问题,今天的计算机系统使用工业标准编码。一个重要的标准名为 ASCII(美国信息交换标准代码)。ASCII 用数字 0 ~ 127 来表示通常(美国)计算机键盘上有的字符以及被称为控制代码的某些特殊值,用于协调信息的发送和接收。”)
  7. T(见 p.92 “表 5.3 一些字符串方法”)
  8. F(p.94 “我们的简单编码/解码程序使用非常弱的加密形式,称为“替换密码”。”,p.95 “由于每个字母总是由相同的符号编码,因此解码器可以使用关于各种字母频率的统计信息和一些简单的试错法测试来发现原始消息。”)
  9. F(p.93 “append 方法可以在列表末尾添加一项。这通常用于每次一项地构建列表。”)
  10. F

多项选择

  1. 访问字符串中的单个字符称为____。
    a. 切片
    b. 连接
    c. 赋值
    d. 索引
  2. 以下____项与 s[0:-1] 相同。
    a. s [-1]
    b. s [:]
    c. s [:len(s)-1]
    d. s [0:len(s)]
  3. ____函数给出了字符的 Unicode 值。
    a. ord
    b. ascii
    c. chr
    d. eval
  4. 以下____项不能用于将数字字符串转换为数字。
    a. int
    b. float
    c. str
    d. eval
  5. 包括(几乎)所有书面语言的字符的、ASCII 的后继标准是____。
    a. TELLI
    b. ASCII ++
    c. Unicode
    d. ISO
  6. ____字符串方法将字符串的所有字符转换为大写。
    a. capitalize
    b. capwords
    c. uppercase
    d. upper
  7. format 方法中填充的字符串“插槽”标记为____。
    a. %
    b. $
    c. []
    d. {}
  8. 下列不是Python 中的文件读取方法。
    a. read
    b. readline
    c. readall
    d. readlines
  9. 使用文件进行输入和输出的程序的术语是____。
    a. 面向文件的
    b. 多行
    c. 批处理
    d. lame
  10. 在读取或写入文件之前,必须创建文件对象____。
    a. open
    b. create
    c. File
    d. Folder

解答

  1. d
  2. c(p.82 “切片产生从 start 直到(但不包括)end 位置给出的子串。”)
  3. a
  4. c
  5. c
  6. d
  7. d
  8. c
  9. c(p.103 “在批处理时,程序输入和输出通过文件完成。”)
  10. a

讨论

  1. 给定初始化语句:
s1 = "spam"
s2 = "ni!"

写出以下每个字符串表达式求值的结果。
​ a. "The Knights who say, " + s2
​ b. 3 * s1 + 2 * s2
​ c. s1[1]
​ d. s1[1:3]
​ e. s1[2] + s2[:2]
​ f. s1 + s2[-1]
​ g. s1.upper()
​ h. s2.upper().ljust(4) * 3

解答

a. ‘The Knights who say, ni!’
b. ‘spamspamspamni!ni!’
c. ‘p’
d. ‘pa’
e. ‘ani’
f. ‘spam!’
g. ‘SPAM’
h. 'NI! NI! NI! ’

  1. 给定与上一个问题相同的初始化语句,写出一个 Python 表达式,可以通过对 s1 和 s2 执行字符串操作构造以下每个结果。
    a. “NI”
    b. “ni!spamni!”
    c. “Spam Ni! Spam Ni! Spam Ni!”
    d. “spam”
    e. [“sp”,“m”]
    f. “spm”

解答

a. s2.upper()[:-1]
b. s2 + s1 + s2
c. ((s1.ljust(5) + s2.ljust(4)) * 3).title()[:-1]
d. s1
e. s1.split(‘a’)
f. ‘’.join(s1.split(‘a’))

注:该题方法有很多,例如 c 还可以通过 ’ '.join([s1, s2] * 3).title() 构造,f 还可以通过 s1.replace(‘a’, ‘’) 构造等。

  1. 显示以下每个程序片段产生的输出:
a. for ch in "aardvark":
       print(ch)
b. for w in "Now is the winter of our discontent...".split():
       print(w)
c. for w in "Mississippi".split("i"):
       print(w, end=" ")
d. msg = ""
   for s in "secret".split("e"):
       msg = msg + s
   print(msg)
e. msg = ""
   for ch in "secret":
       msg = msg + chr(ord(ch)+1)
   print(msg)

解答

a. a
   a
   r
   d
   v
   a
   r
   k
b. Now
   is
   the
   winter
   of
   our
   distent...
c. M ss ss pp 
d. scrt
e. tfdsfu
  1. 写出以下每个字符串格式化操作产生的字符串。如果操作不合法,请解释原因。
a. "Looks like {1} and {0} for breakfast".format("eggs", "spam")
b. "There is {0} {1} {2} {3}".format(1,"spam", 4, "you")
c. "Hello {0}".format("Susan", "Computewell")
d. "{0:0.2f} {0:0.2f}".format(2.3, 2.3468)
e. "{7.5f} {7.5f}".format(2.3, 2.3468)
f. "Time left {0:02}:{1:05.2f}".format(1, 37.374)
g. "{1:3}".format("14")

解答

a. ‘Looks like spam and eggs for breakfast’(注意 0 和 1 的顺序)
b. ‘There is 1 spam 4 you’
c. ‘Hello Susan’(我觉得应该是这里的字符串中只有 “{0}” 一个“插槽”,所以只使用 format 的第一个参数。见 p.98 “索引告诉哪个参数被插入到插槽中”)
d. ‘2.30 2.30’(根据 p.97,插槽说明形式:{<索引>:<格式说明>},格式说明形式:<宽度>.<精度><类型>,可知两个“插槽”插入的都是第一个参数,且精度为2,类型为定点数)
e. 错误(见 d 的说明。花括号中得有冒号(:)以表示所引或格式说明)
f. ‘Time left 01:37.37’(“{0:02}” 中的第一个 0 表示索引第一个参数,第二个 0 表示填充字符,2 表示宽度为 2;”{1:05.2f}“ 中的 1 表示索引第二个参数,0 表示填充字符,5 表示宽度为 5,2 表示精度为 2,f 表示类型为定点数。详见 p.98)
g. 错误(format 只有一个参数,无法插入索引为 1 的第二个参数)

  1. 解释为什么公钥加密比私人(共享)密钥加密更有利于保护因特网上的通信。

解答

私钥必须由双方提前知道。当与互联网上的网站通信时,比如说电子商务,双方交换私钥是没有实际可行性的。

编程练习

  1. 字符串格式化可以用来简化 dateconvert2.py 程序(该程序在本章示例代码中,可下载获得)。用字符串格式化方法重写该程序。

解答

#   dateconvert2 using string formatting

def main():
    # get the day month and year as numbers
    day = int(input("Enter the day number: "))
    month = int(input("Enter the month number: "))
    year = int(input("Enter the year: "))

    date1 = "{0}/{1}/{2}".format(month, day, year)

    months = ["January", "February", "March", "April", 
              "May", "June", "July", "August", 
              "September", "October", "November", "December"]
    monthStr = months[month-1]
    date2 = "{0} {1}, {2}".format(monthStr, day, year)

    print("The date is {0} or {1}.".format(date1, date2))

main()
  1. 某个 CS 教授给出了 5 分测验,等级为 5-A、4-B、3-C、2-D、1-F、0-F。编写一个程序,接受测验分数作为输入,并打印出相应的等级。

解答

#   A program that accepts a quiz score as an input and prints out the corresponding grade

def main():
    score = int(input("Enter the score: "))
    grade = ['F', 'E', 'D', 'C', 'B', 'A'][score]
    print("The grade is {0}.".format(grade))

main()

3.某个 CS 教授给出 100 分的考试,分数等级为 90~100:A、80~89:B、70~79:C、60~69:D、<60:F。编写一个程序,接受考试成绩作为输入,并打印出相应的等级。

解答

#   A program that converts an exam grade to a letter grade

def main():
    score = int(input("Enter the score: "))
    grade = "FFFFFFDCBAA"[score // 10]
    print("The grade is {0}.".format(grade))

main()
  1. 首字母缩略词是一个单词,是从短语中的单词取第一个字母形成的。例如,RAM 是“random access memory”的缩写。编写一个程序,允许用户键入一个短语,然后输出该短语的首字母缩略词。注意:首字母缩略词应该全部为大写,即使短语中的单词没有大写。

解答

#   A program that builds acronyms
def main():
    score = input("Enter the words: ")
    print("The acronym is {}.".format(''.join(i[0].upper() for i in score.split())))

main()
  1. 数字命理学家声称能够基于名字的“数值”来确定一个人的性格特征。名字的值的确定方法是名字中字母的值之和,其中“a”为 1、“b”为 2、“c”为 3,直到“z”为 26。例如,名字“Zelle”具有的值为 26 + 5 + 12 + 12 + 5 = 60(顺便说一下,这恰好是一个非常吉利的数字)。编写一个程序,计算输入的单个名字的数值。

解答

#   A program that computes the 'number value' of a name

def main():
    name = input("Enter the name: ")
    value = 0
    for letter in name.lower():
        value += ord(letter) - ord('a') + 1
    print("The value is {}.".format(value))

main()
  1. 扩展前一个问题的解决方案,允许计算完整的名字,如“John Marvin Zelle”或“John Jacob Jingleheimer Smith”。总值就是所有名字的数值之和。

解答

#   A program that computes the 'number value' of a full name

def main():
    name = input("Enter the full name: ")
    value = 0
    for letter in ''.join(name.lower().split()):
        value += ord(letter) - ord('a') + 1
        
    print("The value is {}.".format(value))

main()
  1. 凯撒密码是一种简单的替换密码,其思路是将明文消息的每个字母在字母表中移动固定数字(称为密钥)。例如,如果键值为 2,则单词“Sourpuss”将被编码为“Uqwtrwuu”。原始消息可以通过使用密钥的负值“重新编码”来恢复。编写一个可以编码和解码凯撒密码的程序。对程序的输入将是明文的字符串和密钥的值。输出将是一个编码消息,其中原始消息中的每个字符都将被替换为 Unicode 字符集中后移密钥个字符。例如,如果 ch 是字符串中的字符,key 是要移位的量,则替换 ch 的字符可以计算为 chr(ord(ch) + key)。

解答

#   A program that can enconde Caesar ciphers

def main():
    message = input("Enter the message: ")
    key = int(input("Enter the key: "))
    encoded_message = ''.join(chr(ord(ch) + key) for ch in message)
    
    print("The enconded message is: {}.".format(encoded_message))

main()
  1. 上一个练习有一个问题,它不处理“超出字母表末端”的情况。真正的凯撒密码以循环方式移动,其中“z”之后的下一个字符是“a”。修改上一个问题的解决方案,让它循环。你可以假定输入只包含字母和空格。(提示:创建一个包含字母表所有字符的字符串,并使用此字符串中的位置作为代码。你不必将“z”转换成“a”,只需确保在字母表字符串中对整个字符序列中使用循环移位。)

解答

#   A program that can enconde Caesar ciphers

def main():
    message = input("Enter the message: ")
    key = int(input("Enter the key: "))
    chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"
    encoded_message = ''.join(chars[((chars.find(ch) + key)) % len(chars)] for ch in message)
    
    print("The enconded message is: {}.".format(encoded_message))

main()
  1. 编写一个程序,计算用户输入的句子中的单词数。

解答

#   A program that counts words in a sentence

def main():
    phrase  = input("Enter the phrase: ")
    count = len(phrase.split())
    
    print("Number of words is {0}.".format(count))

main()

注:count 还可以通过 count = phrase.count(" ") + 1 来计算

  1. 编写一个程序,计算用户输入的句子中的平均单词长度。

解答

#   A program that calculates the average word length in a sentence

def main():
    phrase  = input("Enter the phrase: ")
    count = len(phrase.split())
    length = (len(phrase) - count + 1) / count

    print("The average word length is {0}.".format(length))

main()

这里没有考虑句子中可能存在的其他标点符号,统一按空格分割后当作单词

  1. 编写第1 章中的 chaos.py 程序的改进版本,允许用户输入两个初始值和迭代次数,然后打印一个格式很好的表格,显示这些值随时间的变化情况。例如,如果初始值为 0.25 和 0.26(10 次迭代),表格可能如下所示:
index    0.25         0.26
----------------------------
  1    0.731250     0.750360
  2    0.766441     0.730547
  3    0.698135     0.767707
  4    0.821896     0.695499
  5    0.570894     0.825942
  6    0.955399     0.560671
  7    0.166187     0.960644
  8    0.540418     0.147447
  9    0.968629     0.490255
 10    0.118509     0.974630

解答

#   An improved version of the chaos.py program from Chapter 1

def main():
    x1 = float(input("Enter the first seed between 0 and 1: "))
    x2 = float(input("Enter the second seed between 0 and 1: "))
    print()
    print("index{:8}{:11}".format(x1, x2))
    print("-------------------------------")
    for i in range(1, 11):
        x1 = 3.9 * x1 * (1 - x1)
        x2 = 3.9 * x2 * (1 - x2)
        print("{:>3}{:>12f}{:>12f}".format(i, x1, x2))

main()
  1. 编写第 2 章中的 futval.py 程序的改进版本。程序将提示用户投资金额、年化利率和投资年数。然后程序将输出一个格式正确的表,以年为单位跟踪投资的价值。输出可能如下所示:
Year     Value
----------------
 0     $2000.00
 1     $2200.00
 2     $2420.00
 3     $2662.00
 4     $2928.20
 5     $3221.02
 6     $3542.12
 7     $3897.43

解答

#   An improved version of the futval.py program from Chapter 2

def main():
    principal = eval(input("Enter the initial principal: "))
    apr = float(input("Enter the annual interest rate: "))
    years = int(input("Enter the number of years: "))
    print()
    print("Year     Value")
    print("-------------------")
    for i in range(years + 1):
        print("{0:<8}${1:.2f}".format(i, principal))
        principal = principal * (1 + apr)

main()
  1. 重做所有以前的编程问题,让它们采用批处理(使用文本文件进行输入和输出)。

这题……看看就好

  1. 单词计数。UNIX/Linux 系统上有一个通用实用程序,名为“wc”。该程序分析一个文件以确定其中包含的行数、单词数和字符数。编写你自己的 wc 版本。程序应接受文件名作为输入,然后打印三个数字,显示文件的行数、单词数和字符数。

解答

#   A program that analyzes a file to determine the number of lines, words and characters contained therein

def main():
    filename = input("Enter the filename: ")
    infile = open(filename, 'r')
    chars = infile.read()
    words = chars.split()
    lines = chars.split("\n")
    infile.close()

    print("Lines:", len(lines))
    print("Words:", len(words))
    print("Characters:", len(chars))
    
main()
  1. 编写一个程序来绘制学生考试成绩的水平柱状图。你的程序应该从文件获取输入。文件的第一行包含文件中学生数量的计数,后续每行包含学生的姓氏,后跟一个0~100 范围内的分数。你的程序应为每个学生绘制一个水平柱形,其中柱形的长度表示学生的分数。柱形应该对齐左边缘排列。(提示:使用学生的人数来确定窗口的大小及其坐标。加分需求:在柱形左边标注学生姓名。)
    5-15

解答

from graphics import *

def main():
    # Introduction
    print("This program plots a horizontal bar chart of student exam scores.")
    # Get the count of the number of students from a file
    infile = open("scores.txt", "r")
    count = int(infile.readline())  #.strip())
    i = 0
    last = ['' for i in range(count)]
    score = [0 for i in range(count)]
    for line in infile:
        # Get the last names and score from line
        last[i], score[i] = line.split()
        i += 1
    score = [int(s) for s in score]
    infile.close()

    # 找到最长的名字去控制窗口宽度
    max_last = max([len(l) for l in last])

    
    lastWidth = (max_last + 1) * 10
    barWidth = (max_last - 1) * 20

    winWidth = lastWidth + barWidth
    winHeight = count * 40  # 用 40 是因为我觉得这个数字不错,没别的理由
    barHeight = 30  # bar 与 bar 之间有 20 像素的间隔
    # Create a graphics window
    win = GraphWin("Student Exam Scores", winWidth, winHeight)
    win.setBackground("white")

    barHeight = 30
    # Text last and draw bars for each students
    for i in range(count):
        Text(Point((max_last + 1) * 5, 20 + i * 40), last[i]).draw(win)
        # Draw bar for this student
        percent = score[i] / 100
        bar = Rectangle(Point(lastWidth, 5 + i * 40), Point(lastWidth + (barWidth - 20) * percent, 5 + i * 40 + barHeight))
        bar.setFill(color_rgb(144, 144, 144))
        bar.draw(win)
        Text(bar.getCenter(), score[i]).draw(win)

    input("Press <Enter> to quit")
    win.close()

main()

Student Exam Scores

  1. 编写一个程序来绘制测验分数直方图。程序应从文件读取数据。该文件的每一行包含一个在 0 ~10 范围内的数字。程序必须计算每个分数的出现次数,然后为每个可能分数(0~10)绘制具有柱形的垂直柱形图,其高度对应于该分数。例如,如果 15 个学生得到 8,那么 8 的柱的高度应该是 15。(提示:使用一个列表来存储每个可能得分的计数。)
    直方图的示例如下。
    5-16

解答

from graphics import *
from tkinter.filedialog import askopenfilename

def main():
    # Get scores from a file
    infile = open(askopenfilename(), "r")
    s = [int(i) for i in infile.readlines()]
    infile.close()
    c = [s.count(i) for i in range(11)]
    c_max = max(c)

    # Create a graphics window
    win = GraphWin("Grade Histogram", 352, 180)
    win.setBackground("white")

    for i in range(11):
        Text(Point(16 + i * 32, 170), i).draw(win)
        if c[i] == 0:
            continue
        bar = Rectangle(Point(4 + i * 32, 160), Point(28 + i * 32, 160 - c[i] * 140 / c_max))
        bar.setFill(color_rgb(144, 144, 144))
        bar.draw(win)
        Text(Point(16 + i * 32, 160 - c[i] * 140 / c_max - 10), c[i]).draw(win)

    input("Press <Enter> to quit")
    win.close()

main()

Grade Histogram

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有一只海豚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值