带你读本炒菜书-【原创】
哈喽,大家好,我是知道。
今天给大家来详细聊聊最近读的一本耳熟能详的python秘籍cookbook。
这本书现在已经出了第三版,依旧值得大家一读。
第一章:数据结构和算法
1. 解压可迭代对象赋值给多个变量
>>> *trailing, current = [10, 8, 7, 1, 9, 5, 10, 3]
>>> trailing
[10, 8, 7, 1, 9, 5, 10]
>>> current
3
2. 最后有限几个元素的历史记录
from collections import deque
def search(lines, pattern, history=5):
previous_lines = deque(maxlen=history)
for line in lines:
if pattern in line:
yield line, previous_lines
previous_lines.append(line)
# Example use on a file
if __name__ == '__main__':
with open(r'../../cookbook/somefile.txt') as f:
for line, prevlines in search(f, 'python', 5):
for pline in prevlines:
print(pline, end='')
print(line, end='')
print('-' * 20)
我们在写查询元素的代码时,通常会使用包含 yield 表达式的生成器函数,这样可以将搜索过程代码和使用搜索结果代码解耦。
使用 deque(maxlen=N) 构造函数会新建一个固定大小的队列。当新的元素加入并且这个队列已满的时候,最老的元素会自动被移除掉。
在队列两端插入或删除元素时间复杂度都是 O(1) ,而在列表的开头插入或删除元素的时间复杂度为 O(N) 。
3. 从一个集合中获得最大或者最小的 N 个元素列表(使用堆)
import heapq
nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
print(heapq.nlargest(3, nums)) # Prints [42, 37, 23]
print(heapq.nsmallest(3, nums)) # Prints [-4, 1, 2]
# 也可接受关键字参数,用于更复杂数据结构中
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'])
expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price'])
- N较小时,函数 nlargest() 和 nsmallest()
- N=1的元素的话,那么使用 min() 和max() 函数会更快些
- N 的大小和集合大小接近的时候,通常先排序这个集合然后再使用切片操作会更快(sorted(items)[:N] 或者是 sorted(items)[-N:])
4. 实现一个优先级队列,priority越大优先级越高(使用堆)
import heapq
class PriorityQueue:
def __init__(self):
self._queue = []
self._index = 0
def push(self, item, priority):
# 构建堆时,默认是创建小堆,及最上面的元素始终是最小的,所以-priority表示最大, index表示优先级相同时,谁先进就谁最大
heapq.heappush(self._queue, (-priority, self._index, item))
self._index += 1
def pop(self):
print(self._queue)
return heapq.heappop(self._queue)[-1]
函数 heapq.heappush() 和 heapq.heappop() 分别在队列 _queue 上插入和删除第一个元素,并且队列 _queue 保证第一个元素拥有最高优先级。heappop() 函数总是返回”最小的”的元素,这就是保证队列 pop 操作返回正确元素的关键。另外,由于 push 和 pop操作时间复杂度O(log N),其中 N 是堆的大小,因此就算是 N 很大的时候它们运行速度也依旧很快。
5. 字典中的键映射多个值
-
你可以很方便的使用 collections 模块中的 defaultdict 来构造这样的字典。defaultdict 的一个特征是它会自动初始化每个 key 刚开始对应值
from collections import defaultdict d = defaultdict(list) d['a'].append(1) d['a'].append(2) d['b'].append(4) d = defaultdict(set) d['a'].add(1) d['a'].add(2) d['b'].add(4)
-
方法二
d = {} # A regular dictionary d.setdefault('a', []).append(1) d.setdefault('a', []).append(2) d.setdefault('b', []).append(4) print(d) # {'a': [1, 2], 'b': [4]}
6. 字典排序
- 可 以 使 用 collections 模 块 中 的OrderedDict 类。在迭代操作的时候它会保持元素被插入时的顺序
from collections import OrderedDict d = OrderedDict() d['foo'] = 1 d['bar'] = 2 d['spam'] = 3 d['grok'] = 4 # Outputs "foo 1", "bar 2", "spam 3", "grok 4" for key in d: print(key, d[key])
需要注意的是,一个 OrderedDict 的大小是一个普通字典的两倍,因为它内部维护着另外一个链表。所以如果你要构建一个需要大量 OrderedDict 实例的数据结构的时候(比如读取 100,000 行 CSV 数据到一个 OrderedDict 列表中去),那么你就得仔细权衡一下是否使用 OrderedDict 带来的好处要大过额外内存消耗的影响。
- 可 以 使 用 collections 模 块 中 的OrderedDict 类。在迭代操作的时候它会保持元素被插入时的顺序
7. 在数据字典中执行一些计算操作(比如求最小值、最大值、排序等等)
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}
min_price = min(zip(prices.values(), prices.keys()))
# min_price is (10.75, 'FB')
max_price = max(zip(prices.values(), prices.keys()))
# max_price is (612.78, 'AAPL')
prices_sorted = sorted(zip(prices.values(), prices.keys()))
# prices_sorted is [(10.75, 'FB'), (37.2, 'HPQ'),
# (45.23, 'ACME'), (205.55, 'IBM'),
# (612.78, 'AAPL')]
执行这些计算的时候,需要注意的是 zip() 函数创建的是一个只能访问一次的迭代器。
- 你在一个字典上执行普通的数学运算,你会发现它们仅仅作用于键,而不是值。比如:
min(prices) # Returns 'AAPL' max(prices) # Returns 'IBM'
- 你可能还想要知道对应的键的信息(比如哪种股票价格是最低)
min(prices, key=lambda k: prices[k]) # Returns 'FB'
- 很不幸,你如果想知道值还需要再取一次值
min_value = prices[min(prices, key=lambda k: prices[k])]
- 需要注意的是在计算操作中使用到了 (值,键) 对。当多个实体拥有相同的值的时候,键会决定返回结果。
>>> prices = { 'AAA' : 45.23, 'ZZZ': 45.23 } >>> min(zip(prices.values(), prices.keys())) (45.23, 'AAA') >>> max(zip(prices.values(), prices.keys())) (45.23, 'ZZZ')
8. 怎样在两个字典中寻寻找相同点(比如相同的键、相同的值等等)
一个字典就是一个键集合与值集合的映射关系。字典的 keys() 方法返回一个展现键集合的键视图对象。它们支持集合操作,比如集合并、交、差运算
a.keys() & b.keys() # { 'x', 'y' } # Find keys in a that are not in b a.keys() - b.keys() # { 'z' } # Find (key,value) pairs in common a.items() & b.items() # { ('y', 2) }
是不是加深了你对常用方法的理解,后台回复:炒菜 即可下载最新中文版cookbook
最后
更多Python知识尽在【Python都知道】公众号,欢迎大家!!
扫描下方二维码,关注公众号,了解更多Python内容