python核心编程-第7章课后习题答案

时间:2021-09-05 09:07:51

7-1 字典方法。那个字典方法可以用来把两个字典合并到一起

dict1.update(dict2)

7–5. userpw2.py. 

下面的问题和例题7.1 中管理名字-密码的键值对数据的程序有关。
(a)修改那个脚本,使它能记录用户上次的登录日期和时间(用time 模块),并与用户密码一起保存起来。程序的界面有要求用户输入用户名和密码的提示。无论户名是否成功登录,都应有提示,在户名成功登录后,应更新相应用户的上次登录时间戳。如果本次登录与上次登录在时间上相差不超过4 个小时,则通知该用户: “You already logged in at: <last_ login_timestamp>.”
(b) 添加一个“管理”菜单,其中有以下两项:(1)删除一个用户 (2)显示系统中所有用户的名字和他们的密码的清单。
(c) 口令目前没有加密。请添加一段对口令加密的代码(请参考crypt, rotor, 或其它加密模块)
(d) 为程序添加图形界面,例如,用Tkinter 写。
(e) 要求用户名不区分大小写。
(f) 加强对用户名的限制,不允许符号和空白符。
(g)合并“新用户”和“老用户”两个选项。如果一个新用户试图用一个不存在的用户名登录,
询问该用户是否是新用户,如果回答是肯定的,就创建该帐户。否则,按照老用户的方式登录。

from datetime import datetime
import hashlib
db={}
def newuser():
value=[]
prompt='login name desired again: '
while True:
name=raw_input(prompt).lower()
if not name.isalnum() and '' in name:
print 'name format error'
continue
else:
if db.has_key(name):
prompt='name taken,try another: '
continue
else:
break
pwd=raw_input('login passwd desired: ')
m=hashlib.md5()
m.update(pwd)
value.append(m.hexdigest())
value.append(datetime.now())
db[name]=value
print 'new user is %s, register time is %s' %(name,db[name][1])

def olduser():
name=raw_input('login name desired again: ').lower()
pwd=raw_input('login passwd desired: ')
m=hashlib.md5()
m.update(pwd)
passwd=db.get(name)
if passwd[0]==m.hexdigest():
newtime=datetime.now()
if (newtime-db[name][1]).days==0 and (newtime-db[name][1]).seconds<14400:
print 'you already logged in at %s: ' %(db[name][1])
else:
passwd[1]=newtime
print 'welcome back %s, login time is %s' %(name,passwd[1])

else:
print 'login incorrect'

def removeuser():
print db
name=raw_input('input a user name to remove: ').lower()
if name in db:
db.pop(name)
else:
print 'input error'

def userlogin():
while True:
name=raw_input('login name desired: ').lower()
if not name.isalnum() and '' in name:
print 'name format error'
continue
else:
if not db.has_key(name):
print 'user name is not in db'
answer=raw_input('register a new user? y/n').lower()
if 'y'==answer:
newuser()
break
elif 'n'==answer:
break
else:
print 'user name is already in db'
olduser()
break

def showmenu():
prompt="""
(U)ser Login
(R)emove a existing user
(Q)uit
Enter choice:"""

done=False
while not done:
chosen=False
while not chosen:
try:
choice=raw_input(prompt).strip()[0].lower()
except (EOFError,keyboardInterrupt):
choice='q'
print '\nYou picked: [%s]' % choice
if choice not in 'urq':
print 'invalid option,try again'
else:
chosen=True

if choice=='q':
done=True
if choice=='r':
removeuser()
if choice=='u':
userlogin()

if __name__=='__main__':
showmenu()


7-6. 列表和字典。

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

tlist=[]   
idict = {}
while True:      mark=raw_input('pls input a stock mark: ')      if mark=='--':          break      stock=raw_input('pls input a stock name: ')      price=raw_input('pls input a stock price: ')      current=raw_input('pls input a stock current price: ')      print      tlist.append([mark,stock,price,current])  print '0 mark'  print '1 stock'  while True:      num=int(raw_input('pls input a key to sort: '))      if num==0:          for i in range(0,len(tlist)):            idict.update({tlist[i][0]:tlist[i]})        for eachkey in sorted(idict):              print 'idict key ',eachkey,' has value ',idict[eachkey]          break      elif num==1:          for i in range(0,len(tlist)):              idict.update({tlist[i][0]:tlist[i]})         for eachkey in sorted(idict):              print 'idict key ',eachkey,' has value ',idict[eachkey]          break      else:          print 'input key wrong'          continue  


7-8. 人力资源。

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

adict = {}
bdict = {}
while 1:
name = raw_input('enter Employee name(Q is qiut):')
if name == 'Q':
break
number = raw_input('enter Employee number:')

adict[name] = number
bdict[number] = name
print "1:sort with name.\n 2:sort with number."
while 1:
choice = raw_input('enter you choice:')
if choice == '1':
for key in sorted(adict):
print "result name is:",key,"number is:",adict[key]
elif choice == '2':
for key in sorted(bdict):
print "result name is:",key,"number is:",bdict[key]
else:
print "worry enter"
break
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).


#coding=utf-8

def tr(srcstr,dststr,string,variable):
mylist = []
if variable == '1': #处理不区分大小写
idict = dict(zip(srcstr.lower(),dststr))
if len(srcstr) > len(dststr):
idict.update({}.fromkeys(srcstr[len(dststr):].lower()))
for ch in string.lower():
if ch in idict:
mylist.append(idict[ch])
else:
mylist.append(ch)
elif variable == '2':
idict = dict(zip(srcstr,dststr))
if len(srcstr) > len(dststr):
idict.update({}.fromkeys(srcstr[len(dststr):]))
for ch in string:
if ch in idict:
mylist.append(idict[ch])
else:
mylist.append(ch)
else:
print "variable enter worry"

mylist = [ch for ch in mylist if ch] #列表解析,如果ch不是None,输出ch
print ''.join(mylist) #将列表转换为字符串

if __name__ =="__main__":
srcstr = raw_input('enter Source string:') #输入源字符串
dststr = raw_input('enter Destination string:') #输入目标字符串
string = raw_input('enter Basic string:') #输入基本字符串
variable = raw_input('1:Capital ignore 2:Distinguish Capital:')
tr(srcstr,dststr,string,variable)

特殊情况不能实现,如s rcstr= 'abcDef'    dststr= 'mno'    string= 'AbcdefGhi'   variable=1


7–10. 加密。
(a) 用上一个练习的思路编写一个"rot13"翻译器。"rot13"是一个古老而又简单的加密方法,它把字母表中的每个字母用其后的第13 个字母来代替。字母表中前半部分字母将被映射到后半部分,而后半部分字母将被映射到前半部分,大小写保持不变。举例来说,'a'将被替换为'n','X'将被替换为'K'; 数字和符号不进行翻译。
(b)在你的解决方案的基础上加一个应用程序,让它提示用户输入准备加密的字符串(这个算法同时也可以对加密后的字符串进行解密),如下所示:
% rot13.py
Enter string to rot13: This is a short sentence. Your string to en/decrypt was: [Thisis 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: [Guvfvf n fubeg fragrapr.].
The rot13 string is: [This is a short sentence.].


借鉴别人的答案,觉得非常好

import string

upperdict = {}
lowerdict = {}

upper = string.uppercase
lower = string.lowercase

mylist = []

entersting = raw_input('Enter string to rot13:')
print "You string to en/decrypt was:[",entersting,"]"

for i in range(len(upper)):
if i <13:
upperdict[upper[i]]=upper[i+13]
else:
upperdict[upper[i]]=upper[i-13]

for i in range(len(lower)):
if i <13:
lowerdict[lower[i]]=lower[i+13]
else:
lowerdict[lower[i]]=lower[i-13]

for ch in entersting:
if ch in upperdict:
mylist.append(upperdict[ch])
elif ch in lowerdict:
mylist.append(lowerdict[ch])
else:
mylist.append(ch)

mylist = ''.join(mylist)

print "The rot13 string is:[",mylist,"]"

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


import random

A = set()
B = set()
for i in range(11):
A.add(random.randint(0,9))
B.add(random.randint(0,9))

print 'A is:',A,'B is:',B

anwser2 = []
for count in range(3):
anwser1 = (raw_input('please enter for A|B:')).split(',')
for j in anwser1:
anwser2.append(int(j))
if set(anwser2) == (A|B):
print 'you anwser is right!'
break
else:
if count == 2:
print 'The anwser of A|B is:',A|B
break
else:
print "you are wrong,"
continue

anwser3 = []
for count in range(3):
anwser4 = (raw_input('please enter for A&B:')).split(',')
for j in anwser4:
anwser3.append(int(j))
if set(anwser3) == (A&B):
print 'you anwser is right!'
break
else:
if count == 2:
print 'The anwser of A&B is:',A&B
break
else:
print "you are wrong,"
continue

#
C = set()
D = set()
for i in range(5):
C.add(random.randint(0,15))
for i in range(3):
D.add(random.randint(0,8))
print "C is:"C,"D is:",D
for count in range(3):
anwser5 = raw_input('D is subset of C ? Y/N:')
if anwser5.lower() == 'y':
if D.issubset(C):
print 'you are right'
break
else:
if count == 2:
print "the subset D is ",D.issubset(C)
else:
print 'you are wrong'
continue
elif anwser5.lower() == 'n':
if D.issubset(C):
print 'you are wrong'
continue
else:
if count == 2:
print "the subset D is ",D.issubset(C)
else:
print 'you are right'
break