当前位置: 首页 > 后端技术 > Python

Python自学日记7——字典

时间:2023-03-26 17:15:39 Python

学会把复杂的问题拆解成你已经掌握的基本问题才是正确的学习方法1.写一个函数,读取words.txt,把它们作为key保存到一个字典里,还有使用in来检查一个词是否在字典中。据说这并不难。首先读取单词列表,然后以单词为key,以空字符为value。那么代码如下:defread_dict():fin=open('words.txt')words_dict={}forlineinfin:word=line.split()words_dict[word]=''returnwords_dictread_dict()TypeError回溯(最近调用last)in7words_dict[word]=''8returnwords_dict---->9read_dict()inread_dict()5forlineinfin:6word=line.split()---->7words_dict[word]=''8returnwords_dict9read_dict()TypeError:unhashabletype:'list'但是报错,具体原因不清楚,只能循环取出来对比fin=open('words.txt')forlineinfin:word=line.split()print(word)['aa']['aah']['aahed']['aahing']['aahs']['aal']['aalii']['aaliis']['aals']是这样显示的,我记得有我之前看的时候没有方括号,仔细看,发现错误在word=line.split(),split用于拆分。本来这里应该用strip去掉空格。我只是凭记忆写的。然后改defread_dict():fin=open('words.txt')words_dict={}forlineinfin:word=line.split()words_dict[word]=''returnwords_dictread_dict()这次显示正常了,如果下面没有校验词字典中这段代码没有问题,但是需要用字典来校验某个词是否在字典的key中,而字典是函数中的局部引用和不能在别处使用,所以当检查单词是否在字典中时,会报错:words_dictisnotdefined,所以需要放在函数外,最后改成如下:fin=open('words.txt')words_dict={}defread_dict():forlineinfin:word=line.strip()words_dict[word]=''returnwords_dictread_dict()'hello'inwords_dict代码输出正常,不过总觉得这个方法有点奇怪,说不定会有更好的方法,以后再说2.使用字典作为计数器setdefhistogram(s):d=dict()forcins:ifcnotind:d[c]=1else:d[c]+=1returndh=histogram('faljgaldkjalgkjeweraldfjsl')print(h){'f':2,'a':4,'l':5,'j':4,'g':2,'d':2,'k':2,'e':2,'w':1,'r':1,'s':1}这是比较常规的做法,字典有一个get方法,它接收一个key和一个默认值,如果key出现在字典中,get返回对应的值,否则返回默认值,然后用get替换上面的代码defhistogram(s):d=dict()forcins:d[c]=int(d.get(c,'0'))+1returndh=histogram('faljgaldkjalgkjeweraldfjsl')print(h)get默认值设置为0,如果c不在d中,返回0,加1,d[c]=1,下次查这个值的时候,因为d中会返回1,然后加一变成2,这样就循环得到结果,省去了判断条件3.翻转字典会改变值把原字典的键变成新字典的键,原字典的键变成新字典的值。原来的方法是遍历key,然后每次都将对应的value和新的字典进行比较。如果没有新的键值对,如果有,就在原值上加一个新值definvert_dict(d):invert=dict()forkeyind:val=d[key]ifvalnotininvert:invert[val]=[key]else:invert[val].append(key)returninvertd=histogram('parrot')print(d)invert_dict(d){'p':1,'a':1,'r':2,'o':1,'t':1}{1:['p','a','o','t'],2:['r']}字典有setdefault方法,通过该方法可以更简洁的写出上面的函数:setdefault(key['default']):如果字典中存在键key,则返回其值。如果不存在,则插入值为default的键key并返回default。默认默认为无。根据上面的描述,我们需要先做几个实验,因为我们需要在空字典中添加键值对,我们需要用空字典来测试setdefault方法a=dict()a.setdefault('b',1)返回值为1,print(a)的返回为{'b':1},所以如果字典中没有,就会根据内容转换成键值对括号里,放入字典,然后测试a.setdefault('b',2)print(a)的返回值还是{'b':1},基本就明白了。如果已经存在,则返回值还是1。我们需要增加key的值,如果key在循环中已经存在于字典中,那么只要一开始就设置为空字符,但是需要测试类型:type(a.setdefault('a',''))返回值为str,然后测试是否可以将空字符串转换成列表list(a.setdefault('a',''))returnvalue是[],那么你可以写代码definvert_dict(d):invert=dict()forkeyind:val=d[key]invert[val]=list(invert.setdefault(val,'')).append(key)returninvertd=histogram('parrot')invert_dict(d)TypeErrorTraceback(最近调用last)in7returninvert8d=histogram('parrot')---->9invert_dict(d)ininvert_dict(d)4forkeyind:5val=d[key]---->6invert[val]=list(invert.setdefault(val,'')).append(key)7返回反转8d=histogram('parrot')TypeError:'NoneType'objectisnotiterable报错原因网上查了下。它通常发生在将None分配给多个值时。还是需要拆成小代码块来校验b=dict()b['a']=list(b.setdefault('a','')).append('hello')print(b)returnvalue为{'a':None},本来预计后面会改的结果hello,使用append没有效果,尝试换成"+"b=dict()b['a']=list(b.setdefault('a',''))+['hello']print(b){'a':['hello']}这次返回值是正常的。上面报错说明appendkey的值为None,报错。接下来,将append更改为“+”definvert_dict(d):invert=dict()forkeyind:val=d[key]invert[val]=list(invert.setdefault(val,''))+[key]returninvertd=histogram('parrot')invert_dict(d)这次返回结果正常阅读答案代码如下definvert_dict(d):"""反转一个字典,返回一个从val到key列表的映射。如果映射key->val出现在d中,那么在新字典中val映射到a包含键的列表。d:dict返回:dict"""inverse={}forkey,valind.items():inverse.setdefault(val,[]).append(key)returninverseif__name__=='__main__':d=dict(a=1,b=2,c=3,z=1)inverse=invert_dict(d)#forval,keysininverse.items():#print(val,keys)打印(inverse)我发现了一些问题。首先不知道d.items()中的key,val可以用字典,可以省点代码。dict.items返回的对象(是一个动态视图,当字典改变时,视图也会改变。另外,答案使用inverse.setdefault(val,[]).append(key)而不是赋值给value,也就是说我对这个setdefault不是很理解。另外,我还发现了一个问题,我用的是'',答案是[],但是我把它保存下来,转成一个列表。我更清楚的是有和没有返回值的情况,例如[1,2]+[3]返回值是[1,2,3]但是有[1,2].append('3'),返回value为None,这就解释了为什么前面会报上面的错误。4.写一个程序,读入wordlist,找到所有的rotationpairs。rotationpair:两个单词,如果一个可以用rotation转换成另一个操作,变成旋转对,比如ad一步变成be。当你遇到一个大问题,没有头绪的时候,先想想怎么把这个问题分解成你已经做过的事情。你在读入词表之前已经做了,在ROT13练习中你已经做了旋转操作。然后大体的思路就是读入单词列表,将每个单词从1步到25步遍历旋转,因为26步本身就是,然后检查旋转后的单词是否在单词列表中,如果是,则打印出这两个字就是了。importbisectdefrotate_word(word,num):#rotatewordnew_word=''forletterinword:ifletter.isupper():start=ord('A')elifletter.islower():start=ord('a')new_word=new_word+(chr((ord(letter)-start+num+26)%26+start))returnnew_word#rotate_word('melon',-10)deffind_lt(a,x):#查找是否是单词isInwordlisti=bisect.bisect_left(a,x)ifi!=len(a)anda[i]==x:returnTruereturnNonedefread_words():#Readwordlistfin=open('words.txt')t=[]forlineinfin:word=line.strip()t.append(word)returntdefsdf():t=read_words()forsint:foriinrange(1,26):new_words=rotate_word(s,i)iffind_lt(t,new_words):print(s,i,new_words)sdf()总结:注意方法或函数是否有返回值。用今天的眼光来看,有时候你会发现答案给出的代码中会有一些内置的函数或者方法,让编程变得非常简单。这当然很好,还是多看标准库吧。但是能够在不知不觉中做到这一点也很不错。就像你刚开始学英语一样,更好的练习方法是用你掌握的一些简单的词汇来描述一些你没有遇到过的复杂事物或情况。所以一是多掌握一些简单的方法,学会把复杂的问题转化为你掌握的方法来解决。