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