【CookBook】 Chapter1

collections.deque

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

1
2
3
4
5
6
7
8
9
10
11
12
>>> 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
>>> 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

heapq

字典操作

1. 寻找相同点(比如相同的键、相同的值等等)
1
2
a = {'x' : 1,'y' : 2,'z' : 3}
b = {'w' : 10,'x' : 11,'y' : 2}
1
2
3
4
5
6
# Find keys in common
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) }
1
2
3
# Make a new dictionary with certain keys removed
c = {key:a[key] for key in a.keys() - {'z', 'w'}}
# c is {'x': 1, 'y': 2}
2. 字典排序
1
2
3
4
5
6
7
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}
为了对字典值执行计算操作,通常需要使用zip()函数先将键和值反转过来。
1
2
3
4
5
6
7
8
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()函数创建的是一个只能访问一次的迭代器。

3. OrderedDict

4. 合并-ChainMap
现在有多个字典或者映射,你想将它们从逻辑上合并为一个单一的映射后执行某些操作,比如查找值或者检查某些键是否存在
1
2
3
4
5
6
7
8
a = {'x': 1, 'z': 3 }
b = {'y': 2, 'z': 4 }

from collections import ChainMap
c = ChainMap(a,b)
print(c['x']) # Outputs 1 (from a)
print(c['y']) # Outputs 2 (from b)
print(c['z']) # Outputs 3 (from a)
  • 对于字典的更新或删除操作总是影响的是列表中第一个字典

序列(列表)操作

1. 切片–slice
内置的slice()函数创建了一个切片对象,供切片命名
1
2
3
4
record = '....................100 .......513.25 ..........'
SHARES = slice(20, 23)
PRICE = slice(31, 37)
cost = int(record[SHARES]) * float(record[PRICE])
部分属性及方法
1
2
3
4
5
6
7
>>> a = slice(5, 50, 2)
>>> a.start
5
>>> a.stop
50
>>> a.step
2
另外,你还能通过调用切片的indices(size)方法将它映射到一个确定大小的序列上,这个方法返回一个三元组(start,stop,step),所有值都会被合适的缩小以满足边界限制,从而使用的时候避免出现IndexError异常。
1
2
3
4
5
6
7
8
9
>>> s = 'HelloWorld'
>>> a.indices(len(s))
(5, 10, 2)
>>> for i in range(*a.indices(len(s))):
... print(s[i])
...
W
r
d
2. 排序–itemgetter,attrgetter
都可以用lambda表达式替代,但使用内置函数效率更高

*字典列表排序*
通过使用operator模块的itemgetter函数,可以非常容易的排序这样的数据结构
1
2
3
4
5
6
rows = [
{'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
{'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> from operator import itemgetter
>>> rows_by_fname = sorted(rows,key=itemgetter('fname'))
>>> rows_by_uid = sorted(rows,key=itemgetter('uid'))

>>> rows_by_fname
[{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'},
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'},
{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'},
{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'}]
>>> rows_by_uid
[{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'},
{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'},
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'},
{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'}]

# itemgetter()函数也支持多个keys
>>> rows_by_lfname = sorted(rows, key=itemgetter('lname','fname'))
>>> rows_by_lfname
[{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'},
{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'},
{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'},
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'}]
排序类型相同的对象
1
2
3
4
5
6
class User:
def __init__(self, user_id):
self.user_id = user_id

def __repr__(self):
return 'User({})'.format(self.user_id)
1
2
3
>>> from operator import attrgetter
>>> sorted(users, key=attrgetter('user_id'))
[User(3), User(23), User(99)]
3. 分组–itertools.groupby()
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
>>> rows = [
{'address': '5412 N CLARK', 'date': '07/01/2012'},
{'address': '5148 N CLARK', 'date': '07/04/2012'},
{'address': '5800 E 58TH', 'date': '07/02/2012'},
{'address': '2122 N CLARK', 'date': '07/03/2012'},
{'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},
{'address': '1060 W ADDISON', 'date': '07/02/2012'},
{'address': '4801 N BROADWAY', 'date': '07/01/2012'},
{'address': '1039 W GRANVILLE', 'date': '07/04/2012'},
]

>>> for date, items in groupby(rows, key=itemgetter('date')):
print(date)
for i in items:
print(' ', i)

07/01/2012
{'date': '07/01/2012', 'address': '5412 N CLARK'}
{'date': '07/01/2012', 'address': '4801 N BROADWAY'}
07/02/2012
{'date': '07/02/2012', 'address': '5800 E 58TH'}
{'date': '07/02/2012', 'address': '5645 N RAVENSWOOD'}
{'date': '07/02/2012', 'address': '1060 W ADDISON'}
07/03/2012
{'date': '07/03/2012', 'address': '2122 N CLARK'}
07/04/2012
{'date': '07/04/2012', 'address': '5148 N CLARK'}
{'date': '07/04/2012', 'address': '1039 W GRANVILLE'}
4. 过滤–itertools.compress()
以一个 iterable 对象和一个相对应的Boolean选择器序列作为输入参数。然后输出 iterable 对象中对应选择器为True的元素
也可以通过filter()和推导式
1
2
3
4
5
6
7
8
9
10
11
addresses = [
'5412 N CLARK',
'5148 N CLARK',
'5800 E 58TH',
'2122 N CLARK'
'5645 N RAVENSWOOD',
'1060 W ADDISON',
'4801 N BROADWAY',
'1039 W GRANVILLE',
]
counts = [ 0, 3, 10, 4, 1, 7, 6, 1]
1
2
3
4
5
6
>>> from itertools import compress
>>> more5 = [n > 5 for n in counts]
>>> more5
[False, False, True, False, False, True, True, False]
>>> list(compress(addresses, more5))
['5800 E 58TH', '4801 N BROADWAY', '1039 W GRANVILLE']

【CookBook】 Chapter1
http://blog.rainna.xyz/2020/12/08/2020-12-08-Chapter1/
作者
rainnalv
发布于
2020年12月8日
许可协议