学习python时,记录自己或观察别人从错误到正确的思路,远比只看正确答案要好得多-CharlieFu1.写一个函数,接收一个数字列表并返回其累加和,例如[1,2,3]的累加和为[1,3,6]看到求和就想到了前面用到的内置函数sum(t),但是sum只说是求list中所有的值并且,不知道能不能求出部分和,需要做个测试。t=[1,2,3]sum(t[:2])的返回值为3,表示可以使用sum,然后得到如下代码:defcumulative_sum(t):res=[]foriinrange(len(t)-1):#一开始以为后面会有i+1。以前这里需要减一,但是我忽略了":(i+1)"不包括右边的i+1,所以不需要减一。res.append(sum(t[:(i+1)]))returnrest=[1,2,3]cumulative_sum(t)returnvalue是[1,3],所以去掉负一即可。defcumulative_sum(t):res=[]foriinrange(len(t)):res.append(sum(t[:(i+1)]))returnrest=[1,2,3]cumulative_sum(t)这里有两点需要注意,在res之后使用append,我只写了res[i]=sum(t[:(i+1)]),这样混淆了字典和列表方法,而且":"在t[:(i+1)]被遗忘,这也会导致错误。需要注意这些细节,这些bug可以直接显示出来,但是刚才的minus显示正常但是不符合预期的结果。因为我们知道预期的结果,所以我们可以检查出问题。如果我们不知道,那将很困难。我们还是需要在写代码的时候,提前想清楚。可以通过三种方式从列表中删除元素。注意三者的区别,是否有返回值:t.pop(),pop修改列表,返回删除的值。默认删除最后一个delt[i],删除后不返回。值,可以使用切片来移除多个值如果知道要移除的元素但不知道下标,可以使用remove,返回值为None对象,值:a='banana'b='banana'aisboutputisTruec=[1,2,3]d=[1,2,3]cisdoutputisFalse在a和b前面,我们会说他们是一样的。在这个例子中,python只创建了一个自送货车对象,a和b都引用了它。而后两者我们可以说c和d是相等的,因为它们有相同的元素,但又不相同。因为它们不是同一个对象。两个对象相同则不相等,相等则不一定相等。注意相同和相等的区别。区分修改列表的操作和创建新列表的操作很重要。比如append就是修改列表,“+”就是新建一个列表。t1=[1,2]t2=t1.append(3)print(t1)print(t2)[1,2,3]None#t2返回None表示t1.append(3)没有返回值t3=t1+[4]print(t3)[1,2,3,4]切片操作将创建一个新列表deftail(t):returnt[1:]letters=['a','b','c']rest=tail(letters)print(rest)['b','c']2.写一个函数is_anagram,接收两个字符串,当它们是回文时返回True。一个字母可以得到另一个回文。我理解这个提示,但感觉不对。上网查了一下,只发现了一些回文的诗,但是那一首是前面说的,是倒序的,所以很奇怪。回文和倒序有什么区别?现在先按照提示写defis_anagram(word1,word2):ifword1.sorted()==word2:returnTruereturnFalseis_anagram('ab','ba')AttributeErrorTraceback(mostrecentcalllast)in4returnTrue5returnFalse---->6is_anagram('ab','ba')inis_anagram(word1,word2)1#Exercise:写一个函数is_anagram,接收两个字符串,当它们是回文时返回True2defis_anagram(word1,word2):---->3ifword1.sorted()==word2:4returnTrue5returnFalseAttributeError:'str'objecthasnoattribute'sorted'错误提示字符串不能用sorted,可能是内存错误,再用sort试试defis_anagram(word1,word2):ifword1.sort()==word2:returnTruereturnfalseis_anagram('ab','ba')还是报同样的错误,然后才想起字符串不能改。如果要排序的话,貌似得先把字符串转成列表。defis_anagram(word1,word2):如果"".join(list(word1).sort())==word2或"".join(list(word2).sort())==word1:返回TruereturnFalseis_anagram('hello','ab')我的想法是先把字符串转成列表,然后排序,然后用".join"把分开的字母重新组合起来。结果是以下错误:inis_anagram(word1,word2)1defis_anagram(word1,word2):---->2if"".join(list(word1).sort())==word2or"".join(list(word2).sort())==word1:3returnTrue4returnFalse5is_anagram('hello','ab')TypeError:canonlyjoinaniterable那里是怀疑sort()没有返回值,然后试了下没有,于是用sorted(t)试了返回值,然后改代码如下:defis_anagram(word1,word2):如果"".join(sorted(list(word1)))==word2或"".join(sorted(list(word2)))==word1:返回True返回Falseis_anagram('hello','ello')这次是正常的,上面说了,需要注意是否有返回值3.生日悖论编写一个has_duplicates函数,它接收一个列表并在任何元素出现多次时返回True。它不应修改原始列表。首先想到的是计算列表中每个元素的数量。当任何一个超过1时,返回Truedefhas_duplicates(t):forsint:ift.count(s)>1:returnTruereturnFalset=[1,3,2]has_duplicates(t)当然,如果你count之前不知道(我也上网查了用法),可以用笨办法,先排序,然后逐一判断相邻元素是否相同defhas_duplicates1(t):new_t=t[:]#生成新列表new_t.sort()#因为这会修改列表,不会为iinrange(len(new_t)-1)生成新列表:ifnew_t[i]==new_t[i+1]:returnTruereturnFalset=[1,3,3]has_duplicates1(t)如果你的班级有23个学生,其中两人生日相同的概率是多少?可以使用random模块中的randint生成随机整数,查看官方文档。知道randint的用法后,一次只能产生一个随机数。如果要生成23个数,需要使用循环。接下来,您需要计算概率并调用它。所以生成一个函数defrandom_birt(students):t=[]foriinrange(students):t.append(random.randint(1,366))returnt#random_birt(23)defcount_match(students,numbers):t=random_birt(students)#应该放在循环里,否则只会生成随机列表,结果还是一样count=0foriinrange(numbers):ifhas_duplicates(t):count+=1returnco当untcount_match(23,1000)返回1000时,一想就不对了。我发现随机列表没有放在循环中。放入循环后defrandom_birt(students):t=[]foriinrange(students):t.append(random.randint(1,366))#一年算365天,所以生成的范围随机数是1到365returnt#random_birt(23)defcount_match(students,numbers):count=0foriinrange(numbers):t=random_birt(students)ifhas_duplicates(t):count+=1returncountcount_match(23,1000)返回值为494,表示1000次中有494次,两个人生日相同概率接近50%4.写一个函数bisect,接收一个排序好的列表,和一个目标值,当目标值在列表中时,返回它的下标,否则None我想直接用find方法,试试findthelist不能用find,然后通过循环逐个比较defbisect(t,target):foriinrange(len(t)):ift[i]==target:returnireturnNonet=[1,2,3,4,5,6]bisect(t,5)上面的方法是将list中的所有元素和target一一比较,但是有个问题就是如果list很长,速度会比较慢,所以我们可以使用二分查找(列表需要排序),二分查找使用bisect模块(见官方文档):importbisectdeffind_lt(a,x):i=bisect.bisect_left(a,x)#bisect。bisect_left(a,x,lo=0,hi=len(a)),找到x在a中合适的插入点,使得x的左边小于x,右边大于等于xifi!=len(a)anda[i]==x:returnireturnNonet=read_words()find_lt(t,'hello')二分查找大大降低了查找速度。如果列表中有113809个词,需要按照第一种方法查找对应的次数。按照第二种方法,大概17步就可以找到。5.读取文件words.txt生成一个列表importtimedefread_words():fin=open('words.txt')t=[]forlineinfin:word=line.strip()t.append(word)returntstart_time=time.time()t=read_words()elapsed_time=time.time()-start_timeprint(len(t))print(t[:10])print(elapsed_time)6.写一个程序在thewordlist倒序的单词意思是“ad”和“da”倒序,于是就开始想着从头开始循环,检查每个单词的倒序单词是否在单词列表中,然后代码是如下:defremove_duplicates(t):#为了去除重复,但是在验证主程序是否可行之前,函数new_t=[]foriinrange(len(t)):ift[i]notinnew_t:new_t.append(t[i])返回new_t#t=[1,[1,2],[2,1]]#remove_duplicates(t)defdaoxu():a=[]t=read_words()forsint:ifs[::-1]int:a.append(sorted([s,s[::-1]]))returnadaoxu()一直是用来逐一查找的。发现忽略了运行时间。100000个字,每个字倒过来再找一遍,具体时间不够,挺长的,所以需要用二分查找,改成如下元素new_t=[]foriinrange(len(t)):ift[i]notinnew_t:new_t.append(t[i])returnnew_tdeffind_lt(a,x):#Binarysearchi=bisect.bisect_left(a,x)ifi!=len(a)anda[i]==x:returnTruereturnNonedefdaoxu():a=[]t=read_words()#使用上面的列表生成字母表sint:iffind_lt(t,s[::-1])==Trueands!=s[::-1]:a.append(sorted([s,s[::-1]]))returnremove_duplicates(a)daoxu()得到的反向对需要成对不同,所以s!=s[::-1],然后去掉重复项,最后得到想要的结果。7.编写一个程序,找出单词列表中所有的互锁单词。Interlocking:两个词,interleaved每个词去掉一个字母可以组成一个新词,我们称之为interlocking,比如shoe和code可以互锁lockschool。我的想法是,将单词列表中的每个单词根据下标的奇偶性拆分为两个单词,然后检查这两个单词是否在单词列表中。如果是,则它们是互锁的。如果他们不是,他们就不是。但是我在拆分单词时遇到问题:foriinrange(len('hello')):s1=[]s2=[]ifi%2!=0:s1.append(['hello'[i]])elifi%2==0:s2.append('hello'[i])print(s1,s2)返回不符合预期,后来发现s1和s2是放在循环里的,应该放在外面。s1=[]s2=[]foriinrange(len('hello')):ifi%2!=0:s1.append('hello'[i])elifi%2==0:s2.append('hello'[i])print(s1,s2)就这样分成了两个列表,然后通过join将列表拼接成词defhusuo():#a=[]t=read_words()#获取单词表forsint:s1=[]s2=[]foriinrange(len(s)):ifi%2!=0:#Oddsubscripts1.append(s[i])#AlloddnumbersSubscriptsformalistelifi%2==0:#evensubscriptss2.append(s[i])#composeallevensubscriptsintoalistword1=''.join(s1)#joinlistsintocharacters字符串word2=''.join(s2)iffind_lt(t,word1)andfind_lt(t,word2):#同时在单词列表中查找两个单词print(word1+''+word2+''+s)#returnahusuo()想着成对组合单词然后搜索计算量太大的问题,又麻烦。最好拆分单词并反向搜索。另外就是要学会把大问题拆解成小问题。例如,前两步是看你是否可以将一个单词拆分成一个奇偶列表。三互锁单词点击上面的递码微改一下就进行了:defhusuo():#a=[]t=read_words()forsint:s1=[]s2=[]s3=[]foriinrange(len(s)):ifi%3==0:s1.append(s[i])elifi%3==1:s2.append(s[i])else:s3.append(s[i])word1=''.join(s1)word2=''.join(s2)word3=''.join(s3)如果find_lt(t,word1)andfind_lt(t,word2)andfind_lt(t,word3):print(word1+''+word2+''+word3+''+s)#returnahusuo()下面是答案代码:frominlistimport*definterlock(word_list,word):"""检查一个单词是否可以拆分成两个互锁的词。word_list:字符串列表word:string"""evens=word[::2]odds=word[1::2]returnin_bisect(word_list,evens)andin_bisect(word_list,odds)definterlock_general(word_list,word,n=3):"""检查一个单词是否可以拆分为n个互锁的单词。wo