Python踩坑日记——列表推导式,序列乱序,数据去重,列表元素删除,列表转置,队栈实现,IDLE常用快捷键

 

我叫“Snake”,在我佛如来的指引下,我开始了一段取经之路。猴哥的称号是“斗战圣佛”,我的称号是“Python”。一条蛇的取经故事,我称之为《蛇经》。

                                                

 

文章标题已经乱到不知怎么起了,你可以迅速浏览红色标题,挑选自己需要的东西吞(小心别噎到~)。

 

列表推倒式:

 

不是什么特殊点,举个列子[ i * j for i in range(3) for j in range(5)]的结果是什么?

 

有两种情况,他们分别等价于:

                                    

 

答案是前者哈(i为外层循环,j为内层循环),列表推导式中的for循环是按正常逻辑的循环嵌套的顺序书写的。

 

序列乱序:

我们都知道序列怎样排序,有序列(python3中专指list)对象的sort方法(原地的),还有内置函数sorted(重新生成新的容器)。

 

PS:sort方法排序完后,原序列数据就莫得了,sorted函数会返回一个新生成的排序完毕的序列对象,原序列保持不变。也因此,在功能上,我们可以通过sort和sorted实现浅复制和深复制。

 

你晓得怎样把序列乱序吗?(好不容易排好的,还要再弄乱,估计是吃太饱了。)

 

import random

random.shuffle( sequence )

 

“洗牌”这个名字还行,这样就可以把一个序列乱序(原地的)。

                                                     

 

这里再多说一点,修改序列的方法没有返回值,或者说返回值是None。这是Python中对于可变数据类型(或者说对象)的统一设计原则。

比如:

                                                   

 

既然说到了排序,那就说个复杂的序列——dict。

 

我们知道dict中存储的数据是key-value形式的,也就是键值对数据。like that:

 

dic = {1 : 'c', 2 : 'b', 3: 'a'}

 

为什么说它复杂呢,也是因为它每个元素由两个量来表示,问题来了,请按照value来对dict排序。

 

也就是dict里元素的value按照字母顺序进行sort。HOW?

 

刚才说了,两种方法。

 

一:对象自身的sort方法:

l = list(dic.items())

l.sort( key = lambda x : x[1])

                                            

二,sorted方法:

sorted(dic, key = lambda x : x[1])

                           

 

核心点在于key参数的理解,key参数接收一个function,此function的功能是从元素中提取一个用于比较的关键字。而上面我们的key的lambda函数提取的关键字x【1】,也就是元素的第二个项。(字典元素中第一个项是key,第二个项是value。)

 

从此也就引出了,lambda返回的是个function,验证下。

 

                                              

再来个例子巩固:

alist=[{"name":"a","age":20},{"name":"b","age":30},{"name":"c","age":25}],要求按照age的大小进行排序。

 

原理都是一样的,用于比较的关键字,就是元素的'age'(key)的值(value)。

 

 

数据去重:

直接举个例子:['b','c','d','c','a','a'],要求去掉重复的元素。

 

最low的方法:

 

数据结构中的set,本身具有去重的功能,好好利用。

 

l2 = list(set(l1))

 

来看下第一种方法和第二种方法结果的区别:

                                               

 

有看出区别吗?蠢得办法虽然蠢,但是l2仍旧保留着原list中元素的顺序,而使用set的去重方法,list已经面目全非了,看不出原来的元素顺序。

 

如果只是简单的去重任务,后者的方法还不错。如果要求保留原list元素的顺序信息,也不是做不到。

 

前面我们说过,list对象有自己的sort方法,set完后,再排下序就好。至于key是什么呢?当然是l1的index。

 

                                                

我们说过,key参数是个function,证明下上面例子是对的:

                                      

当然还可以用内置函数sorted,一样的。

 

 

列表元素删除:

例子:

l = [1, 1, 2, 2, 1, 2, 1, 1, 2]

删除l中的所有1。

 

最蠢的方法:

                                               

不但蠢,而且很遗憾的说,结果还是错的:

                                            

 

在前面的文章里我们谈过python中变量的实现形式是引用语义,我慢慢说,你静静听。

 

首先说remove函数的功能——移除第一个遇到与参数值一致的元素。

 

                                        

首个循环,指针指向第一个元素——1,if判断条件满足,执行remove(1)。执行完毕后,list已经改变了:

 

                                 

进入下次循环的时候,指针后移,就会移到元素2上。也就是原来list的第二个1元素,因为list的改变加上指针的后移而被错过了。之后的道理都是一样的。认真看下:

 

 

那没有解决办法吗?有啊,我们已经知道了,结果错误是因为list变化引起的,完全可以 循环一个与原list相同的list来进行remove:

 

                                           

循环遍历l[ : ],切片会返回一个新的list,循环的list和操作的list不是同一个,指针的变化,就不会出错了。

 

                                                 

 

其实认真考虑,循环的作用就是个计数功能,为什么这么讲?remove是移除首个遇到的与参数值相同的元素,循环的功能就是在判断remove执行多少次,so:

 

                                          

 

还没完,介绍些其他的方法,以便应对不同问题。

 

1.filter(过滤器),filter(function,sequence):

                                  

 

2.列表推导式(超级pythonic的):

                                               

 

列表转置:

对list:

                                              

实现转置,两种方法:

 

1.列表推导式生成:

[ [r[i] for r in array] for i in range(len(array)) ]

 

                            

 

按照上面我们说到的循环嵌套顺序:

                              

不同之处自己分析吧。

 

2.序列解包 + zip:

这个方法超棒,仔细看,别眨眼,一下就完了。

 

                                                

 

很好理解,*对序列解包,如果是dict的话用 ** 解包。zip我们经常看到,一些压缩文件的后缀名就是zip,zip函数的功能就是将每个元素的对应位置zip到一起。

 

 

实现栈结构:

对于某些特殊的数据,我们用栈(FILO)这种数据结构存储,更方便后面的处理,怎样实现栈?

 

用list就可以,append方法就可以当做进栈的抽象,出栈的呢?用pop()方法。

 

                                             

 

实现队列数据结构:

对于队列结构的实现,同样可以用list,因为list的pop函数是可以提供参数的。比如:

                                                 

也就是说我们可以用pop(0)抽象出队的功能,但是我们通常不这么实现,为什么呢?因为如果你pop列表的第一个元素,那之后的元素都需要往前移位,移动操作越多,效率就越低,如果list中数据很多,那数据处理的大部分时间就会全部浪费在移动数据上。

 

Remember 一个标准库——queue。

 

也不需要去记忆,就是队列那个单词。

 

                                            

用Queue创建队列对象后用put和get抽象“进队”“出队”功能。

 

除外,还有:

对象的queue属性得到队列情况。(可以当成print来使用)

对象的qsize()方法返回队列的大小。(可以当成len来使用)

 

IDLE常用快捷键:

F1 说明文档(超棒的,多看看,虽然是英文的......)

Alt P 上一条命令

Alt N 下一条命令

Alt / 补全命令单词(以上定义过得)

Alt 3 注释(可选中多行)

Alt 4 取消注释

ctrl F6 重启IDLE(交互环境模式下,可以清空前面import的库)

ctrl [ 取消代码缩进(可选中多行)

ctrl ] 缩进代码块

 

结束吧。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值