python核心编程(第二版)参考答案(自制)--第七章·映像和集合类型

###最近自学python,使用的教材是python核心编程(第二版)。自己做了练习题的答案,不管正确与否,算是给自己的一种约束和督促吧。

--------------------------------------------------------------

7-1.*字典方法。哪个字典方法可以用来把两个字典合并到一起。
【答】:dict.update(dict2)将字典dict2的键-值对添加到字典dict。不能使用dict1+dict2这种方式。
--------------------------------------------------------------
7-2.*字典的键。我们知道字典的值可以是任意的Python对象,那字典的键又如何呢?请试着将除数字和字符串意外的其他不同类型的对象作为字典的键,看看哪些类型可以,哪些不行。对那些不能作为字典的键的对象类型,你认为是什么原因呢?
【答案】:
可哈希对象(不变类型)---数字,字符串和元组(但要加以限制)
不可哈希对象(可变类型)--列表,字典,集合
需要注意的是:值相等的数字代表同一个键,元组作为键时,其元素必须是可哈希的。
内建函数hash()可以判断某个对象是否可以做一个字典的键,如果非可哈希类型作为参数传递给hash()方法,会产生TypeError错误,否则会产生hash值,整数。
【注】元组当中的元素存在可变对象时,无法hash。
--------------------------------------------------------------
7-3.*字典和列表的方法。
(a)创建一个字典,并把这个字典中的键按照字母顺序显示出来。
(b)现在根据已经按照字母顺序排列好的键,显示出这个字典中的键和值。
(c)同(b),但这次是根据已按照字母顺序排序好的字典的值,显示出这个字典中的键和值(注意:对字典和哈希表来说,这样做一般没什么实际意义,因为大多数访问和排序(如果需要)都是基于字典的键,这里只把它作为一个练习)。

dict1={'a':4,'b':3,'c':2,'d':1}
for x in sorted(dict1.keys()):
    print x,dict1[x]
print '*'*20
for key1,value1 in sorted(dict1.items(), key=lambda d:d[1],reverse=False):
    print key1,value1
--------------------------------------------------------------

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

list_a=[1,2,3,4]
list_b=['a','b','c','d']
dict1=dict(zip(list_a,list_b))
print dict1
--------------------------------------------------------------

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

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

def ch_dict(dict1):
    dict2=dict()
    for key1,value1 in dict1.items():
        dict2.update({value1:key1})
    print dict1,'=>',dict2
    return dict2

dict1={1:'a',2:'b',3:'c',4:'d'}
ch_dict(dict1)

---------------------------------------

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

def input_data():
    try:
        name=raw_input('Please input the name(\'q\'for quit):').strip()
        number=int(raw_input('Please input the number(\'q\'for quit):').strip())
    except (EOFError,KeyboardInterrupt):
        name='q'
        number='q'
    if (name in 'Qq')or(str(number) in 'Qq'):
        print 'fail to enter data!';return 0
    else:
        data_HR.update({name:number})
        print 'data has been updated!'

def display(number_fisrt=False):
    print '='*30
    if number_fisrt:
        for name,number in sorted(data_HR.items(), key=lambda d:d[1],reverse=False):
            print 'number:%d\tname:%s'%(number,name)
    else:
        for name in data_HR.keys():
            print 'name:%s\tnumber:%d'%(name,data_HR[name])
    print '='*30

data_HR=dict()
#data_HR={'Jerry':1001,'Tom':1003,'Fab':1002}
while True:
    print '''Please enter the choice:
[N]:enter the new data!
[D]:display the updated data(sorted by name)
[R]:display the updated data(sorted by number)
[Q]:Quit!'''
    try:
        choice=raw_input(':').strip()[0].lower()
    except (EOFError,KeyboardInterrupt):
        choice='q'
    if choice not in 'ndrq':
        print 'Invalid option,try again!'
    else:
        if choice=='q':print 'Exit!!';break;
        if choice=='d':display();continue;
        if choice=='r':display(True);continue;
        if choice=='n':input_data();continue;

---------------------------------------

7.9.*翻译。(a)编写一个字符翻译程序(功能类似于Unix中的tr命令)。我们将这个函数叫做tr(),他又三个字符串做参数:源字符串、目的字符串、基本字符串,语法定义如下:def tr(srcstr,dststr,string)。srcstr的内容是你打算“翻译”的字符集合,dststr是翻译后得到的字符集合,而string是你打算进行翻译操作的字符串。举例来说,如果srcstr='abc',dststr='mno',string='abcdef'。那么tr()的输出将是'mnodef'。注意这里len(srcstr)=len(dststr)。在这个联系里,你可以使用内建函数chr()和ord(),但它们并不一定是解决这个问题所必不可少的函数。
(b)在这个函数里增加一个标志函数,来处理不区分大小写的翻译问题。
(c)修改你的程序,使它能够处理删除字符的操作。字符串srcstr中不能够映射到字符串dststr中的中字符的多余字符都将被过滤掉。换句话说,这些字符没有映射到dststr字符串中的任何字符,因此就从函数返回的字符里给过滤掉了。举例来说,如果scrstr='abcdef',dststr='mno',string='abcdefghi',那么tr()将输出'mnoghi',注意这里len(srcstr)>=len(dststr).

def tr(srcstr,dststr,string,Upper_equal_Lower=False):
    srcstr_eq=srcstr
    string_eq=string
    if Upper_equal_Lower:
        srcstr_eq=srcstr.upper()
        string_eq=string.upper()
    if srcstr_eq not in string_eq:
        print string
        return string
    srcstr_len=len(srcstr)
    dststr_len=len(dststr)
    string_len=len(string)
    j=0
    new_string=''
    for x in xrange(string_len-srcstr_len):
        if (x>=j)and(string_eq[x:x+srcstr_len]==srcstr_eq):
            new_string=new_string+string[j:x]
            new_string=new_string+dststr
            j=x+srcstr_len

    new_string=new_string+string[j:]
    print new_string
    return new_string
tr('abcabc','mnok','hAbcabcabcdeabcfg',True)
---------------------------------------

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

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

import string
def rot13_code(orig):
    result=''
    for x in orig:
        if x in string.letters:
            y=string.letters.index(x)
            if y<13:
                result=result+string.letters[y+13]
            elif y<26:
                result=result+string.letters[y+13].lower()
            elif y<39:
                result=result+string.letters[y+13]
            else:
                result=result+string.letters[y-26+13]
        else:
            result=result+x        
    print result
    return result
def rot13_decode(orig):
    result=''
    for x in orig:
        if x in string.letters:
            y=string.letters.index(x)
            if y<13:
                result=result+string.letters[y+26-13]
            elif y<26:
                result=result+string.letters[y-13]
            elif y<39:
                result=result+string.letters[y-13].upper()
            else:
                result=result+string.letters[y-13]
        else:
            result=result+x        
    print result
    return result

rot13_decode(rot13_code('This is a short sentence.'))
---------------------------------------

7-11.*定义。什么组成字典中合法的键?举例说明字典中合法的键和非法的键。
【答】:同7-2
---------------------------------------
7-12.*定义。(a)在数学上,什么是集合?(b)在Python中,关于集合类型的定义是什么?
【答】:(a)集合是把人们的直观的或思维中的某些确定的能够区分的对象汇合在一起,使之成为一个整体(或称为单体),这一整体就是集合。组成一集合的那些对象称为这一集合的元素(或简称为元)。
(b)python中集合对象(set)是一组无序排列的可哈希的值,包含两种类型:可变集合(set)和不可变集合(frozenset),所以set不是可哈希的,frozenset是可哈希的,能当作字典的键。

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

import random
A=set()
B=set()
A_len=random.randint(1,10)
B_len=random.randint(1,10)
while(A_len):
    temp=random.randint(0,9)
    if temp not in A:
        A.add(temp)
        A_len-=1
while(B_len):
    temp=random.randint(0,9)
    if temp not in B:
        B.add(temp)
        B_len-=1
print A,B
print A|B,A&B
---------------------------------------

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

import random
def random_set():
    A=set()
    A_len=random.randint(1,10)
    while(A_len):
        temp=random.randint(0,9)
        if temp not in A:
            A.add(temp)
            A_len-=1
    print A
    return A
def set_ch(string):#string format:[1,23,2] or (2,3,4)
    result_set=set()
    for x in set(string) - set(' [](),'):
        result_set.add(int(x))
    return result_set

step_time=3
A=random_set();B=random_set()
while(step_time):
    print 'answer format:[1,2,3] or (1,2,3),[],()'
    answer_and=raw_input('Please input your answer of A&B:').strip()
    answer_or=raw_input('Please input your answer of A|B:').strip()

    if(set_ch(answer_and)==A&B)and(set_ch(answer_or)==A|B):
        print 'You are right!\nA&B:%s\nA|B:%s'%(answer_and,answer_or)
        break
    else:step_time=step_time-1
if step_time==0:
    print  'The right answer is:\nA&B:%s\nA|B:%s'%(A&B,A|B)
[注]:附加要求没有什么大的区别,故略。

---------------------------------------

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

【答】:略,看情况再补










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值