我叫“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 ] 缩进代码块
结束吧。