1. 解压序列赋值给多个变量
任何的序列(或者可迭代对象)可以通过一个简单的赋值语句解压并赋值给多个变量。
唯一的前提就是变量的数量必须跟序列元素的数量是一样的
p = [4, 5, 6]
a, b, c = p
print(a, b, c)
4 5 6
2. 解压可迭代对象给多个变量
使用Python的星号(*)解决这个问题
解压出来的变量永远是列表类型
record = (1, 2, 3, 4, 5)
first, *number, end = record
print(first, number, end)
1 [2, 3, 4] 5
3. 保留最后N个元素
使用collections.deque
from collections import deque
# 构建一个固定长度为3的队列
q = deque(maxlen=3)
q.append(1)
q.append(2)
q.append(3)
q
deque([1, 2, 3])
q.append(4)
q
deque([2, 3, 4])
4. 保留最大或最小的N的元素
使用heapq模块的两个函数,nlargest()和nsmallest()
import heapq
nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
print(heapq.nlargest(3, nums))
print(heapq.nsmallest(3, nums))
print(max(nums))
print(min(nums))
[42, 37, 23]
[-4, 1, 2]
42
-4
# 可以接受关键字参数,用于更复杂的数据结构
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'])
print(cheap)
print(expensive)
[{'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}]
[{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]
当要查找的元素个数相对比较小的时候,heapq.nsmallest()和heapq.nlargest()是很合适的
如果只是想找唯一的最大或最小就使用max()和min()函数
如果N的大小和集合大小接近的时候,则使用切片操作会更快一点sorted(items)[:N]或者sorted(items)[-N:]
5. 实现一个优先级队列
使用heapq模块的heappush()和heappop()
import heapq
class 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)
q = PriorityQueue()
q.push(Item('foo'), 1)
q.push(Item('bar'), 4)
q._queue
[(-4, 1, Item('bar')), (-1, 0, Item('foo'))]
q.pop()
Item('bar')
6. 字典中的键映射多个值
一个字典就是一个键对应一个单值的映射。
如果你想要一个值映射多个值,需要这多个值放到另外的容器中
d = {
'a' : [1, 2, 3]
}
d
{'a': [1, 2, 3]}
d = {
'a' : {1, 2, 3}
}
d
{'a': {1, 2, 3}}
# 或者可以使用collections.defaultdict
from collections import defaultdict
d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(4)
d
defaultdict(list, {'a': [1, 2], 'b': [4]})
d = defaultdict(set)
d['a'].add(1)
d['a'].add(2)
d['b'].add(4)
d
defaultdict(set, {'a': {1, 2}, 'b': {4}})
7. 字典排序
使用collections模块OrderedDict类
在迭代的时候保存元素被插入时的顺序
注意,3.6 的 dict 是有序的,在此版本之前皆是无序
from collections import OrderedDict
d = OrderedDict()
d['foo'] = 1
d['bar'] = 2
d['spam'] = 3
d['aok'] = 4
for key in d:
print(key, d[key])
foo 1
bar 2
spam 3
aok 4
d = {}
d['foo'] = 1
d['bar'] = 2
d['spam'] = 3
d['aok'] = 4
for key in d:
print(key, d[key])
foo 1
bar 2
spam 3
aok 4
8. 字典的运算(求最大值,最小值,排序等等)
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}
直接使用max函数,是对字典的key值进行操作
可以使用zip函数将键和值反转过来
注意:zip()函数创建的是一个只能访问一次的迭代器
min_price = min(zip(prices.values(), prices.keys()))
max_price = max(zip(prices.values(), prices.keys()))
min_price, max_price
((10.75, 'FB'), (612.78, 'AAPL'))
9. 查找两字典的相同点
可以简单的使用字典的keys()或者items()方法返回结果上执行集合操作
a = {
'x' : 1,
'y' : 2,
'z' : 3
}
b = {
'w' : 1,
'x' : 11,
'y' : 2
}
a.keys() & b.keys()
{'x', 'y'}
a.items() & b.items()
{('y', 2)}
字典的keys()方法返回一个展现键集合的键视图对象
字典的items()方法返回一个包含(键,值)对的元素视图对象
10. 删除序列相同元素并保持排序
def dedupe(items):
seen = set()
for item in items:
if item not in seen:
print('item is {}, seen is {}'.format(item, seen))
yield item
seen.add(item)
a = [1,3,4,5,6,1,3,5]
list(dedupe(a))
item is 1, seen is set()
item is 3, seen is {1}
item is 4, seen is {1, 3}
item is 5, seen is {1, 3, 4}
item is 6, seen is {1, 3, 4, 5}
[1, 3, 4, 5, 6]
def dedupe(items, key=None):
seen = set()
for item in items:
val = item if key is None else key(item)
print('item {} value {}'.format(item, val))
if val not in seen:
yield item
seen.add(val)
a = [ {'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}]
list(dedupe(a, key = lambda d:(d['x'],d['y'])))
item {'x': 1, 'y': 2} value (1, 2)
item {'x': 1, 'y': 3} value (1, 3)
item {'x': 1, 'y': 2} value (1, 2)
item {'x': 2, 'y': 4} value (2, 4)
[{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
匿名函数: 将创建好的匿名函数通过一个变量去接收,使用变量去调用函数
简单使用set()方法构建一个集合,也可以实现消除重复元素,但是元素位置会被打乱
11. 命名切片
给切片命名,使得代码更加清晰可读
record = '....................100 .......513.25 ..........'
# 使用slice切片,并命名
SHARES = slice(20, 23)
PRICE = slice(31, 37)
cost = int(record[SHARES]) * float(record[PRICE])
cost
51325.0
12. 序列中出现次数最多的元素
collctions.Counter类,里面的most_common()
words = [
'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
'my', 'eyes', "you're", 'under'
]
from collections import Counter
word_counts = Counter(words)
# 出现频率最高的3个单词
top_three = word_counts.most_common(3)
print(top_three)
[('eyes', 8), ('the', 5), ('look', 4)]
13. 通过某个关键字排序一个字典列表
operator.itemgetter函数
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}
]
from operator import itemgetter
rows_by_fname = sorted(rows, key=itemgetter('fname'))
rows_by_uid = sorted(rows, key=itemgetter('uid'))
print(rows_by_fname)
print(rows_by_uid)
[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]
[{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}]
min(rows, key = itemgetter('uid'))
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}
14. 排序不支持原生比较的对象
operator.attagetter()函数
class User:
def __init__(self, user_id):
self.user_id = user_id
def __repr__(self):
return 'User({})'.format(self.user_id)
users = [User(23), User(3), User(99)]
from operator import attrgetter
sorted(users, key=attrgetter('user_id'))
[User(3), User(23), User(99)]
15. 通过某个字段将记录分组
itertools.groupby()
16. 过滤序列元素
最简单的办法是列表推导
17. 从字典中提取子集
最简单的办法是字典推导
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}
p1 = {key: value for key, value in prices.items() if value > 200}
print(p1)
{'AAPL': 612.78, 'IBM': 205.55}
tech_names = {'AAPL', 'IBM', 'HPQ'}
p2 = {key: value for key, value in prices.items() if key in tech_names}
print(p2)
{'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.2}
18. 映射名称到序列元素
collections.namedtuple()函数
19. 转换并同时计算数据
nums = [1, 2, 3, 4, 5]
s = sum(x * x for x in nums)
s
55
s = sum((x * x for x in nums)) # 显示的传递一个生成器表达式对象
s= sum((x * x for x in nums) # 更加优雅的实现方式,省略了括号
portfolio = [
{'name':'GOOG', 'shares': 50},
{'name':'YHOO', 'shares': 75},
{'name':'AOL', 'shares': 20},
{'name':'SCOX', 'shares': 65}
]
min_shares = min(s['shares'] for s in portfolio)
min_shares
20
20. 合成多个字典或映射
使用collections.ChainMap类