python cookbook代码段

  • 数据结构和算法

数据结构和算法

将序列的值赋给多个变量

1
2
3
4
5
6
7
8
9
10
11
12
>>> data = ['ACM', 50, 91.1, (2012, 12, 21)]
>>> data
['ACM', 50, 91.1, (2012, 12, 21)]
>>> name, shares, price, date = data
>>> name
'ACM'
>>> shares
50
>>> price
91.1
>>> date
(2012, 12, 21)

有时候,你可能只想解压一部分,丢弃其他的值。对于这种情况Python并没有提供特殊的语法。但是你可以使用任意变量名去占位,到时候丢掉这些变量就行了。

1
2
3
4
5
6
>>> data = ['ACM', 50, 91.1, (2012, 12, 21)]
>>> _, shares, price, _ = data
>>> shares
50
>>> price
91.1

解析未知个数的可迭代对象:星号表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212')
>>> name, email, *phone = record
>>> name
'Dave'
>>> email
'dave@example.com'
>>> phone
['773-555-1212', '847-555-1212']


>>> *trailing, current = [10, 8, 7, 1, 9, 5, 10, 3]
>>> trailing
[10, 8, 7, 1, 9, 5, 10]
>>> current
3

值得注意的是上面解压出的phone_numbers变量永远都是列表类型,不管解压的数量是多少(包括0个)。所以,任何使用到phone_numbers变量的代码就不需要做多余的类型检查去确认它是否是列表类型了。

扩展的迭代解压语法是专门为解压不确定个数或任意个数元素的可迭代对象而设计的。通常,这些可迭代对象的元素结构有确定的规则(比如第1个元素后面都是电话号码),星号表达式让开发人员可以很容易的利用这些规则来解压出元素来。而不是通过一些比较复杂的手段去获取这些关联的的元素值。

结合*_使用

1
2
3
4
5
6
>>> record = ('ACME', 50, 123.45, (12, 18, 2012))
>>> name, *_, (*_, year) = record
>>> name
'ACME'
>>> year
2012

双向队列collections.deque的使用

使用deque(maxlen=N)构造函数会新建一个固定大小的队列。当新的元素加入并且这个队列已满的时候,最老的元素会自动被移除掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> from collections import deque
>>> q = deque(maxlen=3)
>>> q.append(1)
>>> q.append(2)
>>> q.append(3)
>>> q
deque([1, 2, 3], maxlen=3)
>>> q.append(4)
>>> q
deque([2, 3, 4], maxlen=3)
>>> q.append(5)
>>> q
deque([3, 4, 5], maxlen=3)

如果你不设置最大队列大小,那么就会得到一个无限大小队列,同时可以在队列的两端执行添加和弹出元素的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> q = deque()
>>> q.append(1)
>>> q.append(2)
>>> q.append(3)
>>> q
deque([1, 2, 3])
>>> q.appendleft(4)
>>> q
deque([4, 1, 2, 3])
>>> q.pop()
3
>>> q
deque([4, 1, 2])
>>> q.popleft()
4
>>> q
deque([1, 2])

堆:heapq模块

获取队列中最大或最小的N个元素

1
2
3
4
5
6
7
8
>>> import heapq
>>> nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
>>> lar3 = heapq.nlargest(3, nums)
>>> lar3
[42, 37, 23]
>>> sma3 = heapq.nsmallest(3, nums)
>>> sma3
[-4, 1, 2]

两个函数都能接受一个关键字参数,用于更复杂的数据结构中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> portfolio = [
... {'name': 'IBM', 'shares': 100, 'price': 91.1},
... {'name': 'AAPL', 'shares': 50, 'price': 543.22},
... {'name': 'FB', 'shares': 200, 'price': 21.09},
... {'name': 'HPQ', 'shares': 35, 'price': 31.75},
... {'name': 'YHOO', 'shares': 45, 'price': 16.35},
... {'name': 'ACME', 'shares': 75, 'price': 115.65}
... ]
>>> cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])
>>> cheap
[{'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}]
>>> expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price'])
>>> expensive
[{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]

上面代码在对每个元素进行对比的时候,会以price的值进行比较。

对序列排序

1
2
3
4
>>> nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
>>> heapq.heapify(nums)
>>> nums
[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]

堆数据结构一个重要的特征就是heap[0]永远是最小的元素,并且剩余的元素可以通过heapq.heappop()方法得到,改方法会将第一个元素弹出,并用下一个最小的元素来取代被弹出元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
>>> heapq.heapify(nums)
>>> nums
[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]
>>> nums[0]
-4
>>> heapq.heappop(nums)
-4
>>> nums
[1, 2, 2, 23, 7, 8, 18, 23, 42, 37]
>>> heapq.heappop(nums)
1
>>> nums
[2, 2, 8, 23, 7, 37, 18, 23, 42]

当要查找的元素个数相对比较小的时候,函数nlargest()nsmallest()是很合适的。如果你仅仅想查找唯一的最小或最大(N=1)的元素的话,那么使用min()max()函数会更快些。类似的,如果N的大小和集合大小接近的时候,通常先排序这个集合然后再使用切片操作会更快点 (sorted(items)[:N]或者是sorted(items)[-N:])。

hoxis wechat
一个脱离了高级趣味的程序员,关注回复1024有惊喜~
赞赏一杯咖啡
0%