万里行,始于足下。想要练就一双洞察一切的眼睛,还是得先把基本功学好。今天,就带大家仔细回顾一下Python榜单。温故而知新,实属不易。当然复习的时候也要发散思维,因为一些看似微不足道、根深蒂固的语言习惯,比如数组索引为什么从0开始,背后可能有很大的渊源。知道它是什么,还需要知道为什么是喵喵喵~~~最后,在基础知识之上,还需要探索进阶,比如学习生成器表达式,这样你不仅可以掌握基础更扎实,也掌握得好。获得更全面的认知升级。Python列表呢?列表是一个有序的集合,可以随时在其中添加、查找和删除元素。列表支持添加不同数据类型的元素:数字、字符串、列表、元组等。列表可以通过有序索引遍历所有元素,从前到后计数,索引为[0,n-1],从从后面到前面,索引是[-1,-n],其中n是列表的长度。列表可以是没有元素的空列表,也可以包含超多元素(如果内存大小支持的话)。list_a=[]#空列表,即len(list_a)==0list_b=[2018,10,'2018-10-1',['hi',1,2],(33,44)]#list_b长度为5,包含2个数值元素,1个字符串元素,1个列表元素和1个元组元素len(list_b)==5list_b[0]==list_b[-5]==2018lits_b[3]==list_b[-2]==['hi',1,2]lits_b[4]==list_b[-1]==(33,44)Python中如何操作列表?1)创建列表:将元素用方括号[]包裹起来,用逗号分隔元素。使用list()方法转换并生成列表。列表理解/列表理解/列表理解,生成列表。list_a=[1,2,3]list_b=list("abc")#list_b==['a','b','c']list_c=list((4,5,6))#list_c==[4,5,6]list_d=[iforiinlist_a]#list_d==[1,2,3]list_e=[i*jforiinlist_aforjinlist_c]#list_e==[4,5,6,10,12,12,15,18]list_f=[i*jfori,jinzip(list_a,list_c)]#list_f==[4,10,18]list_g=[iforiinlist_aifi%2==0]#list_g==[2]#结合range()函数,range(start,stop[,step])list_h=list(range(3))#list_h==[0,1,2]list_i=list(range(3,7))#list_i==[3,4,5,6]list_j=list(range(3,9,2))#list_j==[3,5,7]#找出100以内能被3整除的正整数list_k=list(range(3,100,3))#list_k==[3,6,9,...,96,99]2)展开列表:使用append()方法在列表末尾添加一个新元素。使用insert()方法在列表中的指定位置添加一个元素。使用“+”运算符将两个列表连接成一个新列表。使用extend()方法将一个列表拼接成另一个列表。#在下面添加2个元素list_a=[]list_a.append('happy')#list_a==['happy']list_a.insert(0,'very')#list_a==['very','happy']#下面两种扩展列表的方式list_1=['I','am']list_2=['very','happy']list_3=list_1+list_2#newlistlist_3==['I','am','very','happy']list_1.extend(list_2)#展开原来的列表1,list_1==['I','am','very','happy']3)删除列表并销毁列表:使用dellist[m]语句删除指定索引m处的元素。使用remove()方法,删除具有指定值(第一次出现)的元素。使用pop()方法,获取并删除列表末尾的单个元素。使用pop(m)方法移除索引值为m的元素。使用clear()方法清除列表中的元素。(杯子还在,水倒空了)用dellist语句销毁整个列表。(杯子和水都没有了)#下面4种删除列表元素的方法list_1=list_2=list_3=list_4=['I','am','very','happy']dellist_1[0]#list_1==['am','very','happy']list_2。remove('I')#list_2==['am','very','happy']list_3.pop()#list_3==['I','am','very']list_4.pop(0)#list_4==['am','very','happy']#清除并销毁list_a=[1,2,3]list_b=[1,2,3]list_b.clear()#list_b==[]dellist_a#没有list_a,再次使用会报错4)列表切片:基本含义:从第i个索引开始,向右移动到最后n位直到元素,按m间隔过滤基本格式:[i:i+n:m];i是切片的起始索引值,当它是列表的第一个位置时可以省略;i+n是切片的结束位置,也就是链表的最后一个位置,可以省略;m可以不提供,默认值为1,不允许为0,当m为负数时,列表将被反转。注意:这些值可以大于列表长度,不会报越界。li=[1,4,5,6,7,9,11,14,16]#下面的写法可以表示整个列表,其中X>=len(li)li[0:X]==li[0:]==li[:X]==li[:]==li[::]==li[-X:X]==li[-X:]li[1:5]==[4,5,6,7]#从1开始,取5-1个元素li[1:5:2]==[4,6]#从1开始,取5-1个元素,过滤li[-1:]==[16]#取倒数第一个元素li[-4:-2]==[9,11]#从倒数第四个取-2-(-4)=2个元素li[:-2]==li[-len(li):-2]==[1,4,5,6,7,9,11]#从头开始??,取-2-(-len(li))=7位元素#注意先翻转列表,再截取li[::-1]==[16,14,11,9,7,6,5,4,1]#翻转整个列表li[::-2]==[16,11,7,5,1]#翻转整个列表,然后按2个区间过滤li[:-5:-1]==[16,14,11,9]#翻转整个列表,取-5-(-len(li))=4位元素li[:-5:-3]==[16,9]#翻转整个列表,取-5-(-len(li))=4位元素,然后按3个区间过滤li[::0]#报错(ValueError:slicestepcannotbezero)5)其他操作:使用len()方法统计所有元素个数。使用count()方法计算具有指定值的元素的数量。使用max()方法统计元素中的最大值(要求元素类型相同;直接比较数字类型,比较其他类型的id)使用min()方法统计元素中的最小值(要求相同元素类型;数字类型直接比较,其他类型比较id)用index()方法,找到指定值元素的索引位置(第一个匹配)。使用reverse()方法反转列表中的元素。使用copy()方法进行浅拷贝并生成新列表。使用deepcopy()方法进行深拷贝并生成新列表。使用sort()方法根据原始列表进行排序。使用sorted()方法根据原始列表的元素对新列表进行排序。list_1=[2018,10,'2018-10-1',['hi',1,2],(33,44)]len(list_1)==5list_1.count(10)==1#元素10numberis1list_1.index(10)==1#元素10的索引为1list_1.reverse()#list_1==[(33,44),['hi',1,2],'2018-10-1',10,2018]#比较浅拷贝和深拷贝importcopylist_a=[2018,10,'2018-10-1',['hi',1,2],(33,44)]list_b=['hi',1,2]list_c=list_a.copy()#list_c==[2018,10,'2018-10-1',['hi',1,2],(33,44)]list_d=复制。deepcopy(list_a)#list_d==[2018,10,'2018-10-1',['hi',1,2],(33,44)]#改变原来的可变对象元素list_a[3]list.append('new')#list_a==[2018,10,'2018-10-1',['hi',1,2,'new'],(33,44)]#可用浅拷贝变量对象会随着原来的列表变化list_c==[2018,10,'2018-10-1',['hi',1,2,'new'],(33,44)]#deepcopy变量object不会随原list改变list_d==[2018,10,'2018-10-1',['hi',1,2],(33,44)]#比较sort()和sorted()list_1=list_2=[2,1,4,6,5,3]list_1.sort()#原始列表变化:list_1==[1,2,3,4,5,6]list_3=sorted(list_2)#The原始列表保持不变:list_2==[2,1,4,6,5,3];list_3==[1,2,3,4,5,6]为什么Python列表索引从0开始?权威解释来自Guidov一篇Rossum(Python之父)的博文:《Why Python uses 0-based indexing》一句话总结:索引从0开始,切片用法很优雅。翻译本质如下:我决定在Python中使用基于0的索引的一个原因是切片语法(slicenotation)。我们先看看切片的使用。也许最常见的用法是“取前n个元素”或“从第i个索引开始,取最后n个元素”(前一种用法实际上是i==start位的特殊用法)。如果这两种用法可以在表达式中没有丑陋的+1或-1的情况下实现,那将是非常优雅的。使用基于0的索引、半开区间切片、默认匹配区间(Python最终采用了这种方式),以上两种情况的切片语法变得非常漂亮:a[:n]和a[i:i+n],前者是a[0:n]的缩写。如果使用从1开始的索引方式,那么,想要a[:n]表达“取前n个元素”的意思,要么使用闭区间切片语法,要么使用切片起始位和切片语法中的切片长度作为切片参数。如果半开区间切片语法与从1开始的索引相结合,它将变得不优雅。如果您使用闭区间切片语法,为了从第i个索引中获取最后n个元素,您必须将表达式写为a[i:i+n-1]。...特别是当两个切片操作在相邻位置时,第一个切片操作的结束索引值是第二个切片操作的起始索引值,太漂亮了,不能丢弃。例如,如果要将字符串在i和j位置分成三部分,则这三部分的表达式为a[:i]、a[i:j]和a[j:]。其他编程语言的索引?索引从0开始的编程语言:C,C++,Python,Java,PHP,Ruby,Javascript...索引从1开始的编程语言:ABC,Matlab,VB,easylanguage,mostshelllanguages...IndexfromProgramming其他值开头的语言:Pascal、Lua……还有表示周、月等序列结构的数据,各种编程语言也分为不同的阵营。他们有什么考虑?C语言:索引从0开始,可以大大提高内存寻址计算的效率。详细分析可以参考《C语言数组元素下标为何从0开始》Mostshelllanguages:大多数都是从1开始,出处参考stackexchangePascal上的这个问答,Lua:Defaultstartsfrom1,但是支持改变初始索引值。原因据说对非专业开发者更友好。来源指的是这个问答。上面列出的原因是最稳妥和得体的解释。话题到这里就该结束了,因为“索引应该从哪个开始最好”和“哪种编程语言最好”一样具有破坏性……优雅而美丽的结局:生成器表达式列表生成器是一个美丽而优雅的东西,但是它有一个致命的缺点:一次性将所有元素加载到内存中,当列表过长时,会占用过多的内存资源,而我们通常只需要使用少量的元素,所以未使用大部分的元素占用的内存成为不必要的开销。生成器是一种更高级、更优雅的东西。它利用“懒加载”的原理,不生成完整列表,而是迭代、即时、按需生成元素,不仅可以大大节省内存空间,而且理论上可以生成无限列表!大多数生成器都是作为函数实现的,但是,它不是返回(return)一个值,而是生成(yield)一个值并暂停程序。然后,通过next()方法立即生成并返回一个元素,或者通过for循环一个一个地生成并返回所有元素。next()效率太低,调用次数超过限制时会抛出StopIteration异常,for循环会自动捕获这个异常停止调用,还是用比较好。#计算斐波那契数列的生成元deffibon(n):a=b=1foriinrange(n):yielda#使用yielda,b=b,a+b#计算前1000000个数,传next()函数依次生成一个数g=fibon(1000000)next(g)#1next(g)#1next(g)#2next(g)#3next(g)#5#依此类推,但是如果调用超过1,000,000次,会报异常StopIteration#计算前1,000,000个数,通过for循环forxinfibon(1000000):print(x)生成的数一个一个打印出来生成器表达式和列表生成公式很相似,只是把[]改成了(),但背后的道理却大相径庭。l=[x*2forxinrange(5)]#列表生成公式,4以内2个整数的倍数g=(x*2forxinrange(5))#generatorexpressiontype(l)#result:
