文章中的代码仅在Python3中测试成功,没有在Python2中测试。
0X00 *表达式 从某个可迭代对象中分解出N个元素,但是这个可迭代的对象可能会超过N,会出现too many values to unpack异常。
比如我这儿有N个统计信息,因为第一次和最后一次的信息不准确需要删除掉,而将中间的信息保留下来,那么就可以这么弄。
1 2 3 4 5 6 7 if __name__ == '__main__' : grade = [23 , 45 , 42 , 45 , 78 , 98 , 89 , 97 , 69 , 77 , 88 , 50 , 65 , 99 , 98 ] first, *new_grade, last = grade print (new_grade)
这里的赋值就是将第一个和最后一个赋给了first和last,而中间的给了new_grade
0X01 定长队列 有一种情况:程序在运行的时候会记录日志,比如说web程序的访问历史。如果我们需要只保留最后的1W条数据,那么很快能想到使用一个列表,每次插入数据的时候判断长度,然后对应的append和del。但是有一个更简单且更快速的方法就是使用collections.deque()
。下面的例子中有一个1024长的列表,我们列表里只存最新的7条。
1 2 3 4 5 6 7 8 9 10 11 12 13 import collectionsif __name__ == '__main__' : auto_queue = collections.deque(maxlen=7 ) my_list = range (1024 ) for i in my_list: auto_queue.append(i) print (auto_queue)
运行之后可以看到,列表里只保存了最后插入的七条数据。
0X02 最大最小的几个元素 当我们有一个列表,需要找到列表里最大的N个元素时,一般会想到先排序然后分片,这想法当然不多,但是还有一个更好用的方法:
1 2 3 4 5 6 7 8 9 10 import heapqif __name__ == '__main__' : my_list = [34 , 234 , 56 , 56 , 345 , 456 , 23 , 213 , 456 , 8 , 98 , 43 , 2 , 67 ] print ('max: ' , heapq.nlargest(3 , my_list)) print ('min: ' , heapq.nsmallest(2 , my_list))
我这里用列表来演示,但是这个方法支持更复杂的数据结构。比如我有一个列表,列表里包含很多个字典,字典里是学生考试信息,那么我就可以用考试分数来找到前三名:
1 2 3 4 5 6 7 8 9 10 11 import heapqif __name__ == '__main__' : my_list = [{'name' : '小明' , 'grade' : 56 }, {'name' : '小红' , 'grade' : 87 }, {'name' : '小刚' , 'grade' : 67 }, {'name' : '小志' , 'grade' : 46 }, {'name' : '小逗逼' , 'grade' : 99 }, {'name' : '小华' , 'grade' : 85 },] print ('max: ' , heapq.nlargest(3 , my_list, key=lambda s: s['grade' ])) print ('min: ' , heapq.nsmallest(3 , my_list, key=lambda s: s['grade' ]))
key 后面的 lambda s: s['grade']
是用了一个 匿名函数 。列表里唯一的值就是排序的关键字。更多关于更多关于匿名函数
如果N相对总数据量来说很小,可以用heapq.heapify()
获得更好的性能。这个函数会将原来的集合转变成列表并以 堆 的形式排序。而堆最重要的一个特性就是最小的那个元素一定在第一位。所以我们可以利用这个性质来获取最小的前N个。
1 2 3 4 5 6 7 8 9 10 11 12 13 import heapqif __name__ == '__main__' : my_list = [234 , 324 , 456 , 567 , 345 , 23 , 546 , 567 , 98 , 45 , 2 , 576 ] heapq.heapify(my_list) print (my_list) print (heapq.heappop(my_list)) print (heapq.heappop(my_list)) print (heapq.heappop(my_list))
0X03 优先级队列 普通队列都是按照FIFO(first in first out)来增删数据,有些特殊情况需要给每个元素设定优先级,push元素的时候设定优先级,pop的时候找到优先级最高的。比如说操作系统的任务调度就是这样的,会给每个进程设置优先级。不过当然,不会使用Python实现的了。这里的内部也是用堆来实现的,所以在15行的位置用了-priority
来让堆反向排、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import heapqclass PriorityQueue : def __init__ (self ): self._queue = [] self._index = 0 def push (self, item, priority ): heapq.heappush(self._queue, (-priority, self._index, item)) self._index += 1 def pop (self ): return heapq.heappop(self._queue)[-1 ] class Item : def __init__ (self, name ): self.name = name def __repr__ (self ): return 'Item({!r})' .format (self.name) if __name__ == '__main__' : my_queue = PriorityQueue() my_queue.push(Item('内核' ), 99 ) my_queue.push(Item('文件复制' ), 40 ) my_queue.push(Item('CS:GO' ), 75 ) print (my_queue.pop())
0X04 一键多值 我们可以轻松的写出用一个键对应多个值的字典,只需要让键对应到列表或者集合就好了,但是要啰里啰嗦写一大堆东西。其实可以用一个内建的方法来解决这个问题。通过这个方法可以快速创建这种字典,也可以像操作普通列表一样操作里面的数据。
1 2 3 4 5 6 7 8 9 10 11 12 from collections import defaultdictif __name__ == '__main__' : my_dic = defaultdict(list ) my_dic['name' ].append('李华' ) my_dic['qq' ].append('66666' ) my_dic['qq' ].append('23333' ) my_dic['qq' ].append('88888' ) print (my_dic)
0X05 分片命名 Python中分片非常好用,有的时候会在程序中出现很多分片,管理起来特别麻烦。可以通过这种方式给分片命名,下次再次调用的时候可以直接使用分片的名字。
1 2 3 4 5 6 7 8 9 10 11 12 if __name__ == '__main__' : data = 'shawn 17 M' name = slice (0 , 5 ) age = slice (7 , 8 ) sex = slice (9 , 10 ) print (data[name]) print (data[age]) print (data[sex])
0X06 词频统计 从一个序列中找到出现次数最多的元素。Counter
对象还可以进行简单的加减,比如a序列里出现了10次’hello’而b序列里出现了3次’hello’,那么a+b的话’hello’的值就会变成13。
1 2 3 4 5 6 7 8 9 10 from collections import Counterif __name__ == '__main__' : data = ['hello' , 'world' , 'hey' , 'hello' , 'world' , 'jack' , 'hey' , 'york' , 'hey' , 'hello' , 'hello' ] word_count = Counter(data) print (word_count.most_common(1 ))
0X07 对字典列表排序 比如我们从数据库中查询到了部分学生的成绩,每个学生的信息存成一个字典,多个字典组成一个列表。然后需要让列表按学生成绩排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from operator import itemgetterif __name__ == '__main__' : student = [ {'name' : '小明' , 'mark' : 98 }, {'name' : '小红' , 'mark' : 87 }, {'name' : '小刚' , 'mark' : 58 }, {'name' : '李华' , 'mark' : 100 } ] student = sorted (student, key=itemgetter('name' )) for i in student: print (i)
0X08 筛选序列 有一个列表,里面全是某次考试的成绩,需要成绩列表中找到所有的不及格成绩。可以轻松写出:定义空列表,for遍历成绩单,判断<60的就append。但是还有一个更方便的方案,就是使用 列表推导式 来完成。更多关于列表推导式
1 2 3 4 5 6 7 if __name__ == '__main__' : my_list = [34 , 56 , 67 , 78 , 95 , 23 , 96 , 23 , 86 , 78 , 89 , 45 ] print ([n for n in my_list if n <= 60 ])
也可以用同样的方式来从字典中筛选子字典。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 if __name__ == '__main__' : mark_list = { '小明' : 58 , '小红' : 94 , '小刚' : 67 , '小智' : 76 , '小亮' : 45 } unpass = {key:value for key, value in mark_list.items() if value < 60 } print (unpass)