您的位置:首页 > 编程语言 > Python开发

Python核心编程-第七章课后题

2016-06-03 00:00 162 查看
摘要: Python核心编程关于字典的课后题

7–1. 字典方法。哪个字典方法可以用来把两个字典合并到一起?

答:应该是dict.update(dict2).可以完成把dict2的键值对添加到dict里面去

[code=language-python]>>> dict1 = {'a':1,'b':2}
>>> dict2 = {'c' : 3}
>>> dict1.update(dict2)
>>> dict1
{'a': 1, 'c': 3, 'b': 2}


7–2. 字典的键。我们知道字典的值可以是任意的 Python 对象,那字典的键又如何呢?请试 着将除数字和字符串以外的其他不同类型的对象作为字典的键,看一看,哪些类型可以,哪些不行? 对那些不能作字典的键的对象类型,你认为是什么原因呢?

答:键必须是可哈希的,因为这样才能通过键来带入哈希函数求得对应的值的内存。如果键变成可变对象,则硬带入哈希函数可能会找不到原来值的内存而造成混乱

[code=language-python]>>> dict3 = {}
>>> dict3['abc'] = 123
>>> dict3[123] = 'abc'
>>> dict3[['a','b']] = 12
Traceback (most recent call last):
File "", line 1, in
TypeError: unhashable type: 'list'
>>> dict3[(1,2)] = 'ab'
>>> dict3[([1,2],3)] = 'aba'
Traceback (most recent call last):
File "", line 1, in
TypeError: unhashable type: 'list'


可以看到,数值,字符串,元组可以作为键对象,但是元组必须是一级的,不能包含列表


7–3. 字典和列表的方法。 (a) 创建一个字典,并把这个字典中的键按照字母顺序显示出来。

(b) 现在根据已按照字母顺序排序好的键,显示出这个字典中的键和值。

(c)同(b),但这次是根据已按照字母顺序排序好的字典的值,显示出这个字典中的键和值。(注 意:对字典和哈希表来说,这样做一般没有什么实际意义,因为大多数访问和排序(如果需要)都是 基于字典的键,这里只把它作为一个练习。)

答:a).

[code=language-python]>>> dict1 = {'a':1,'b':2,'c':3,'d':4}
>>> dict1
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
>>> for i in sorted(dict1):
...     print i,':',dict1[i]
...
a : 1
b : 2
c : 3
d : 4

就算创建出来这个字典再显示的时候就已经不是字母顺序了,哎~,顺序表现出来还是得用sorted()函数

b).同a)

c).

[code=language-python]>>> dict2 = {'animal':'cat','fruit':'apple','plant':'tree'}
>>> for i in sorted(dict2.values()):
...     for key in dict2:
...             if dict2[key] == i:
...                     print "key:", key," and value:", i
...
key: fruit  and value: apple
key: animal  and value: cat
key: plant  and value: tree


7-4. 建立字典。给定两个长度相同的列表,比如说,列表[1, 2, 3,...]和['abc', 'def', 'ghi',...],用这两个列表里的所有数据组成一个字典, 像这样: {1:'abc', 2: 'def', 3: 'ghi',...}

答:题目的本意就是一对一,然后就想到了zip函数,如下:

[code=language-python]>>> list1 = ['abc','def','ghi','jkl']
>>> list2 = [1,2,3,4]
>>> dict(zip(list2,list1))
{1: 'abc', 2: 'def', 3: 'ghi', 4: 'jkl'}


7–5. userpw2.py. 下面的问题和例题 7.1 中管理名字-密码的键值对数据的程序有关。

(a)修改那个脚本,使它能记录用户上次的登录日期和时间(用 time 模块),并与用户密码一起 保存起来。程序的界面有要求用户输入用户名和密码的提示。无论户名是否成功登录,都应有提示, 在户名成功登录后,应更新相应用户的上次登录时间戳。 如果本次登录与上次登录在时间上相差不 超过 4 个小时,则通知该用户: “You already logged in at: .”

(b) 添加一个“管理”菜单,其中有以下两项:(1)删除一个用户 (2)显示系统中所有用户的名 字和他们的密码的清单。

(c) 口令目前没有加密。请添加一段对口令加密的代码(请参考 crypt, rotor, 或其它加密模块)

(d) 为程序添加图形界面,例如,用 Tkinter 写。

(e) 要求用户名不区分大小写。

(f) 加强对用户名的限制,不允许符号和空白符。

(g)合并“新用户”和“老用户”两个选项。 如果一个新用户试图用一个不存在的用户名登录, 询问该用户是否是新用户,如果回答是肯定的,就创建该帐户。否则,按照老用户的方式登录。

答:看到这么多小问,头大了~~~~~~,得了看了大神的博客这道题,蒙圈了,怎么类都用上了,还是有图形界面不得导入一个库吗?另外之前在运行例子的时候,发现用户名和密码必须写入一个文件,否则关闭以后就什么都没有了,更不用提不超过4小时限制了。这道题真的有难度,吃不下

[code=plain]import time
import wx
import string

class UserPw(object):
"""登录系统的类,包含用户登录,超级用户删除用户,显示所有用户
(需要超级用户帐号和密码)"""
def __init__(self):
"""数据的初始化,用户信息保存格式为 用户名:【密码,登录时间(time(),用于计算),登录时间(ctime(),用于显示)】"""
self.db = {}
self._superName = "fzyz.abc"
self._superpasswd = "fzyz"

def userLogin(self, name, passwd):
"""用户的登录,支持新用户和老用户的一起登录,不区分大小写的用户名.新用户自动注册"""
try:
if self.db[name.lower()][0] == passwd:
if time.time() - self.db[name.lower()][1] < 14400:      #登录时间小于4小时
contents.SetValue("you already logged in at:" + str(self.db[name.lower()][2]))
else:
contents.SetValue("welcome back!")
except IndexError:
for i in name.lower():
if i in string.punctuation + string.whitespace:
contents.SetValue("用户名不允许符号和空白符,请重新输入")
return False
self.db[name.lower()] = [passwd, time.time(), time.ctime()]
return True
def delUser(self, name):
"""通过超级用户进行用户的删除"""
if userName == self._superName and userPw == self._superpasswd:
del self.db[name.lower()]
else:
contents.SetValue("超级用户账户或密码输入有误")
return
def showAllUser(self):
"""通过超级用户,显示所有的用户"""
if userName == self._superName and userPw == self._superpasswd:
for key in self.db.keys():
contents.AppendText("用户名:%s", key)
else:
contents.SetValue("超级用户账户或密码输入有误")

def load(event):
oneUser = UserPw()
oneUser.userLogin(str(userName), str(userPw))
def delUser(event):
oneUser = UserPw()
oneUser.delUser(str(name))
def showAllUser(event):
oneUser = UserPw()
oneUser.showAllUser()

if __name__ == "__main__":
app = wx.App()
win = wx.Frame(None, title = "登录系统", size = (410, 335))
userName = wx.TextCtrl(win, pos = (5,5), size = (240, 25))
userPw = wx.TextCtrl(win, pos = (5, 30), size = (240, 25))

contents = wx.TextCtrl(win, pos = (5, 90), size = (390, 260),
style = wx.TE_MULTILINE | wx.HSCROLL)

loadButton = wx.Button(win, label = "登录", pos = (250, 5), size = (80, 25))
loadButton.Bind(wx.EVT_BUTTON, load)

delUserButton = wx.Button(win, label = "删除用户", pos = (5, 60), size = (90, 25))
delUserButton.Bind(wx.EVT_BUTTON, delUser)

showAllUserButton = wx.Button(win, label = "显示所有用户", pos = (100, 60), size = (90, 25))
showAllUserButton.Bind(wx.EVT_BUTTON, showAllUser)

win.Show()
app.MainLoop()


这是大神写的,就看看吧~为了赶进度,就……

7-6. 列表和字典。创建一个简单的股票证券投资数据系统。其中应至少包含四项数据:股市 行情显示器符号, 所持有的股票, 购买价格及当前价位 - 你可以随意添加其他数据项, 比如收益率, 52 周最高指数、最低指数,等等。 用户每次输入各列的数据构成一个输出行。每行数据构成一个列表。 还有一个总列表,包括了 所有行的数据。数据输入完毕后,提示用户选择一列数据项进行排序。把该数据项抽取出来作为字 典的键,字典的值就是该键对应行的值的列表。提醒读者:被选择用来排序的数据项必须是非重复 的键,否则就会丢失数据,因为字典不允许一个键有多个值。 你还可以选择其他计算输出,比如,盈亏比率,目前证券资产价值等。

答:WTF 题?这就好比教会你了1+1,然后出了个练习,Are you kidding me?



真心不会写

7-7. 颠倒字典中的键和值。用一个字典做输入,输出另一个字典,用前者的键做值,前者的 值做键。

答:这个其实很简单,但是在输入的时候出现了一些问题。很有收获!!

raw_input()和input()其实有很大差别,前者你搞出来出来的都是字符格式str,而后者你输入什么,它就是什么,输入字典给的就是字典,输入数字出来数字!就是这么神奇!!

[code=language-python]def swp_dict(dct):
dct_final = {}
for key in dct:
dct_final[dct[key]] = key
return dct_final

if __name__ == '__main__':
while True:
dict1 = input("Please input a dict(-1 to quit):")
if dict1 == -1:
break
else:
print swp_dict(dict1)



7-8. 人力资源。创建一个简单的雇员姓名和编号的程序。让用户输入一组雇员姓名和编号。 你的程序可以提供按照姓名排序输出的功能,雇员姓名显示在前面,后面是对应的雇员编号。附加 题:添加一项功能,按照雇员编号的顺序输出数据。

答:这个不难,就是觉得没必要在写个 函数,只是在写的过程中发现匿名函数还有[(key,dict1[key]) for key in sorted(dict1)]这样的用法~

[code=language-python]if __name__ == '__main__':
dict1 = {}
while True:
list1 = []
name_num = raw_input("Please input a dict key-value pair,like'a:1'('E' to end enroll):")
if name_num.lower() == 'e':
break
else:
list1 = name_num.split(':')
dict1[list1[0]] = list1[1]
for key in sorted(dict1):
print key,dict1[key]

第二个,感觉像是上面写过的题目,为了更方便,我把两种排列都写在了一个函数里面,用户可以选择排列方式

[code=language-python]if __name__ == '__main__':
dict1 = {}
while True:
list1 = []
name_num = raw_input("Please input a dict key-value pair,like'a:1'('E' to end enroll):")
if name_num.lower() == 'e':
word = raw_input("Array it by name(for '1') or number(for '2')?:")
break
else:
list1 = name_num.split(':')
dict1[list1[0]] = list1[1]
if word == '1':
for key in sorted(dict1):
print key,dict1[key]
elif word == '2':
for i in sorted(dict1.values()):
for key in dict1:
if dict1[key] == i:
print i,key
else:
print "Wrong~~"


7-9. 翻译 (a) 编写一个字符翻译程序(功能类似于 Unix 中的 tr 命令)。我们将这个函数叫做 tr(),它有 三个字符串做参数: 源字符串、目的字符串、基本字符串,语法定义如下:
def tr(srcstr, dststr, string) srcstr 的内容是你打算“翻译”的字符集合,dsrstr 是翻译后得到的字符集合,而 string 是 你打算进行翻译操作的字符串。举例来说,如果 srcstr == 'abc', dststr == 'mno', string == 'abcdef', 那么 tr()的输出将是'mnodef'. 注意这里 len(srcstr) == len(dststr). 在这个练习里,你可以使用内建函数 chr() 和 ord(), 但它们并不一定是解决这个问题所必不 可少的函数。

b) 在这个函数里增加一个标志符参数,来处理不区分大小写的翻译问题。
c)修改你的程序, 使它能够处理删除字符的操作。字符串 srcstr 中不能够映射到字符串 dststr 中字符的多余字符都将被过滤掉。换句话说,这些字符没有映射到 dststr 字符串中的任何字符,因 此就从函数返回的字符里被过滤掉了。举例来说:如果 srcstr == 'abcdef', dststr == 'mno', string == 'abcdefghi', 那么 tr()将输出'mnoghi'. 注意这里 len(srcstr) >= len(dststr).

答:

a).说的这么高大尚,其实不就是用dststr替换在string中的srcstr吗?这个函数好像在之前的字符串那一节写过,之前是用list化,现在改用string拼接试试。可是这个跟字典有什么联系呢?

[code=language-python]def tr(srcstr,dststr,string):
string_lenth = len(string)
srcstr_lenth = len(srcstr)
for i in range(string_lenth):
if srcstr == string[i:i+srcstr_lenth]:
new_string = string[0:i] + dststr + string[i+srcstr_lenth:]
return new_string

if __name__ == '__main__':
while True:
srcstr = raw_input("Enter a source word(-1 to quit):")
dststr = raw_input("Enter a desination word:")
string = raw_input("Enter a full string:")
if srcstr == '-1':
break
else:
print tr(srcstr,dststr,string)

b).其实这个也有歧义的,区分大小写是检索的时候区分不区分还是,替换的时候区分不区分,费劲~,我按照的是前者写的

[code=language-python]def tr(srcstr,dststr,string):
string_lenth = len(string)
srcstr_lenth = len(srcstr)
for i in range(string_lenth):
if srcstr == string[i:i+srcstr_lenth]:
new_string = string[0:i] + dststr + string[i+srcstr_lenth:]
return new_string

def tr_non_case(srcstr,dststr,string):     #新增
string_lenth = len(string)
srcstr_lenth = len(srcstr)
for i in range(string_lenth):
if srcstr.lower() == string[i:i+srcstr_lenth].lower():
new_string = string[0:i] + dststr + string[i+srcstr_lenth:]
return new_string

if __name__ == '__main__':
while True:
srcstr = raw_input("Enter a source word(-1 to quit):")
dststr = raw_input("Enter a desination word:")
string = raw_input("Enter a full string:")
switch = raw_input("Case censitive?('Y' or 'N'):")#新增
if srcstr == '-1':
break
elif switch.lower() == 'y':
print tr(srcstr,dststr,string)
elif switch.lower() == 'n':
print tr_non_case(srcstr,dststr,string)
else:
print 'Not kidding!'

c).这个……,我a题中做的就是这种智能的,因为

for i in range(string_lenth):
if srcstr == string[i:i+srcstr_lenth]:
new_string = string[0:i] + dststr + string[i+srcstr_lenth:]

这里拼接的时候用的就是srcstr的长度,直接截掉了srcstr这个字符串


7–10. 加密。 (a) 用上一个练习的思路编写一个"rot13"翻译器。 "rot13"是一个古老而又简单的加密方法, 它把字母表中的每个字母用其后的第 13 个字母来代替。字母表中前半部分字母将被映射到后半部分, 而后半部分字母将被映射到前半部分,大小写保持不变。举例来说,'a'将被替换为'n','X'将被替 换为'K'; 数字和符号不进行翻译。

(b)在你的解决方案的基础上加一个应用程序,让它提示用户输入准备加密的字符串(这个算法 同时也可以对加密后的字符串进行解密),如下所示:

[code=language-python]% rot13.py
Enter string to rot13: This is a short sentence. Your string to en/decrypt was: [This
is a short sentence.].
The rot13 string is: [Guvf vf n fubeg fragrapr.].
%
% rot13.py
Enter string to rot13: Guvf vf n fubeg fragrapr. Your string to en/decrypt was: [Guvf
vf n fubeg fragrapr.].
The rot13 string is: [This is a short sentence.].

答:我觉得上一题跟这个题的关系不大,因为上一题就没用到ASCII编码的值,难度不大

a).

[code=language-python]def rot13(string):
string_lenth = len(string)
list1 = list(string)
list_empty = []
for i in range(string_lenth):
if 97 <= ord(list1[i]) <= 109 or 65 <= ord(list1[i]) <= 77:
list_empty.append(chr(ord(list1[i])+13))
elif 110 <= ord(list1[i]) <= 122 or 78 <= ord(list1[i]) <= 90:
list_empty.append(chr(ord(list1[i])-13))
else:
list_empty.append(list1[i])
return ''.join(list_empty)

if __name__ == '__main__':
while True:
string_ori = raw_input("Enter a string to en rot13(q to quit):")
if string_ori == 'q':
break
else:
print rot13(string_ori)

b).首先小小吐槽一下,我想着用个switch开关来控制编码的加减号,从而控制解码编码问题,然后想到了eval()函数,然后带入由于自身掌握不周,没搞定。后来我想,还是用最傻的方法吧~于是乎又写了个rot13_reverse()函数,仅仅把“+”,“-”互换,后来测试好了,然后我发现!!

惊天秘密有木有!!!

一个字符串用rot13处理以后,表示被编码,然后在用这个得到的在处理一下,就返回当初的字符串了!!也就是说,解码只用把字符串再进行一次编码就可以了!!

擦!怪不得这个加密方式以后不用了,原来太特么坑了

[code=language-python]def rot13(string):
string_lenth = len(string)
list1 = list(string)
list_empty = []
for i in range(string_lenth):
if 97 <= ord(list1[i]) <= 109 or 65 <= ord(list1[i]) <= 77:
list_empty.append(chr(ord(list1[i])+13))
elif 110 <= ord(list1[i]) <= 122 or 78 <= ord(list1[i]) <= 90:
list_empty.append(chr(ord(list1[i])-13))
else:
list_empty.append(list1[i])
return ''.join(list_empty)

if __name__ == '__main__':
while True:
string_ori = raw_input("Enter a string to en rot13(q to quit):")
if string_ori == 'q':
break
else:
print 'Your string to en/decrypt was:[%s].' % string_ori
switch = raw_input('En/decrypt?(E/D):')
if switch.lower() == 'e' or switch.lower() == 'd':
print rot13(string_ori)
else:
print 'Wrong choose!'

基本还是a题的代码,只是加了个e,d的选择,然而选择这个没用,反正底层代码没人看到

7–11. 定义。什么组成字典中合法的键? 举例说明字典中合法的键和非法的键。

答:怎么又是这个题,不是在7-2中说了么?详情已经在2题中说过了,可以去参考一下

7-12. 定义。 (a)在数学上,什么是集合? (b)在 Python 中,关于集合类型的定义是什么?

答:

a).集合是指具有某种特定性质的具体的或抽象的对象汇总成的集体

b).python中没有详细说明什么是集合,只是说从数学上类比一下,集合对象是一组无序排列的哈希值。

7–13. 随机数。修改练习 5-17 的代码:使用 random 模块中的 randint()或 randrange()方 法生成一个随机数集合: 从 0 到 9(包括 9)中随机选择,生成 1 到 10 个随机数。这些数字组成集合 A(A 可以是可变集合,也可以不是)。同理,按此方法生成集合 B。每次新生成集合 A 和 B 后,显示 结果 A | B 和 A & B。

答:还好再5-17的时候把这个题做了。没啥难度。

[code=language-python]from random import *
def gen_num(s):
for i in range(10):
s.add(str(randint(0,9)))
return s

if __name__ == '__main__':
A = set()
B = set()
gen_num(A)
gen_num(B)
print 'A is %s.' % A
print 'B is %s.' % B
print 'The union of the two is %s.' % (A|B)
print 'The intersection of the two is %s.' % (A&B)

少有的几个不用调试直接能用的代码,有点自我膨胀了。

7–14. 用户验证。修改前面的练习,要求用户输入 A | B 和 A & B 的结果,并告诉用户他(或 她)的答案是否正确,而不是将 A | B 和 A & B 的结果直接显示出来。如果用户回答错误,允许他(或 她)修改解决方案,然后重新验证用户输入的答案。如果用户三次提交的答案均不正确,程序将显示 正确结果。 附加题:运用你关于集合的知识, 创建某个集合的潜在子集,并询问用户此潜在子集是否真是 该集合的子集,要求和主程序一样有显示更正和答案的功能。

答:只写了union的方法,intersect的方案直接更换一下符号就可以了

[code=language-python]from random import *
def gen_num(s):
for i in range(10):
s.add(str(randint(0,9)))
return s

if __name__ == '__main__':
A = set()
B = set()
gen_num(A)
gen_num(B)
print 'A is %s.' % A
print 'B is %s.' % B
union_AB = (A|B)
intersection_AB = (A&B)
i = 0
while i < 3:
user_input = raw_input("Try to enter the union of the two\
(',' to divide):")
user_union = set(user_input.split(','))
if union_AB == user_union:
print 'You are so great!'
break
else:
if i <= 1:
print 'Try again!'
i+=1
else:
print 'You lose!'
print 'The answer is %s.' % union_AB
i += 1

附加题:我觉得题目有问题,创建某个集合的潜在子集,难道这个不肯定就是子集吗?为什么还要让用户判断?用户判断了几回发现被骗了(全部都回答‘是’),写这个题的目的又是什么呢?

7–15. 编写计算器。 这个练习取材于 http://math.hws.edu/ 在线免费 Java 教材中的练习 12.2。编写一个程序允许用户选择两个集合:A 和 B, 及运算操作符。例如,in, not in, &, |, ^, <, <=, >, >=, ==, !=, 等. (你自己定义集合的输入语法,它们并不一定要像 Java 示例中那样用方括 号括住。)解析输入的字符串,按照用户选择的运算进行操作。你写的程序代码应该比 Java 版本的 该程序更简洁。

答:我不会Java,应该比Java版本更简洁是个什么意思?我都看不懂的

如果要我写的话肯定是很长一排的if,然后觉得应该有更好的方法,看了大神的,用到了eval()函数,觉得挺不错的

[code=language-python]def cal(set_A,set_B,op):
return eval(str(set_A)+str(op)+str(set_B))

if __name__ == '__main__':
A = raw_input('Enter the first set,like:1,2,3(q to quit):')
B = raw_input('Enter the second set,like:1,2,3:')
option = raw_input('Enter option you want:')
#print type(A),B
A = set(A.split(','))
B = set(B.split(','))
#print type(A),B
#print type(option)
print '%s,%s,%s is %s.' % (A,option,B,cal(A,B,option))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息