-
解压不确定个数或任意个数元素的可迭代对象时可用*星号表达式,得到的是一个列表(即使为空),*_ 可接受多个需要丢弃的元素。
first, *middle, last = grades first, *_ = grades
-
队列使用:collections.deque
- 使用deque(maxlen=N) 构造函数会新建一个固定大小的队列。当新的元素加入并且这个队列已满的时候,最老的元素会自动被移除掉。
- 在队列两端插入或删除元素时间复杂度都是O(1)
-
堆使用:heapq
-
heapq 模块有两个函数:nlargest() 和nsmallest() 可以从一个集合中获得最大或者最小的N 个元素列表
# 两个函数都能接受一个关键字参数,用于更复杂的数据结构中: cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])
-
如果你仅仅想查找唯一的最小或最大(N=1)的元素的话,那么使用min() 和max() 函数会更快。
-
如果N的大小和集合大小接近的时候,通常先排序这个集合然后再使用切片操作会更快点(sorted(items)[:N] 或者是sorted(items)[-N:])
-
-
默认初始化键字典使用:collections 模块中的defaultdict
-
优点:defaultdict 会自动为将要访问的键(就算目前字典中并不存在这样的键)创建映射实体,即不需要单独判断键是否存在,直接使用即可。
from collections import defaultdict d = defaultdict(list) d['a'].append(1) d = defaultdict(set) d['a'].add(1) # 普通字典要实现该功能使用setdefault()。 d = {} # A regular dictionary d.setdefault('a', []).append(1)
-
-
有序字典使用:collections 模块中的OrderedDict 类
- 内部维护着一个双向链表,也因此大小是普通字典的两倍
-
用zip()函数可以将字典的键值反转,然后可以使用min(),sorted()等函数进行运算。
min_price = min(zip(prices.values(), prices.keys())) # min_price is (10.75, 'FB') # 排序 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')]
-
字典的keys()方法和items()方法返回的是集合,因此可以直接做并、交、差运算,即可以找出相同的键,值或键值对等。values()方法不行,可能是因为value无法保证值互不相同。
a = { 'x' : 1, 'y' : 2, 'z' : 3 } b = { 'w' : 10, 'x' : 11, 'y' : 2 } a.keys() & b.keys() # { 'x', 'y' } a.keys() - b.keys() # { 'z' } a.items() & b.items() # { ('y', 2) }
-
删除一个序列中的重复元素,如果可以无序则直接使用set()去重,如果要求有序或者元素不是hashable 类型,比如字典等时,可用下面这种方法,说明:如果key为None则直接使用item运算,如果key接受到一个匿名函数,则按匿名函数的规则,取出相应的值来运算,判断是否重复,并返回值。
def dedupe(items, key=None): seen = set() for item in items: val = item if key is None else key(item) 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']))) [{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
-
利用切片对象:slice()
SHARES = slice(20, 23)
-
切片对象有三个属性a.start、a.stop、a.step
-
可利用indices(size)控制切片大小,避免越界
>>> s = 'HelloWorld' >>> a.indices(len(s)) (5, 10, 2)
-
-
计数:collections.Counter,在底层实现上,一个Counter 对象就是一个字典,将元素映射到它出现的次数上,most_common()返回计数最大的前n。
from collections import Counter word_counts = Counter(words) # 出现频率最高的3 个单词 top_three = word_counts.most_common(3) print(top_three) # Outputs [('eyes', 8), ('the', 5), ('look', 4)]
-
Counter对象可以跟数学运算操作相结合
>>> c = a + b >>> c Counter({'eyes': 9, 'the': 5, 'look': 4, 'my': 4, 'into': 3, 'not': 2, 'around': 2, "you're": 1, "don't": 1, 'in': 1, 'why': 1, 'looking': 1, 'are': 1, 'under': 1, 'you': 1}) >>> d = a - b
-
-
对内容是字典的列表排序:operator 模块的itemgetter,或者使用匿名函数lambda,但是itemgetter会快一点。
from operator import itemgetter rows_by_fname = sorted(rows, key=itemgetter('fname')) rows_by_lfname = sorted(rows, key=itemgetter('lname','fname'))
-
对内容不支持原生比较对象的列表排序:operator模块的attrgetter(),或者使用匿名函数lambda。min(),max()同理。
>>> from operator import attrgetter >>> sorted(users, key=attrgetter('user_id')) [User(3), User(23), User(99)]
-
分组迭代:itertools.groupby()。使用前需要先根据指定字段的数据排序,因为groupby()进检查连续的元素。
from operator import itemgetter from itertools import groupby # Sort by the desired field first rows.sort(key=itemgetter('date')) # Iterate in groups 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'}
-
过滤序列元素:尽量使用列表推导式或生成器表达式,这两种推导式都可以在推导时做处理,也可以添加过滤条件;如果略复杂则使用filter()函数,注意filter()函数返回的是迭代器;也可以使用itertools.compress()函数,第一个参数是可迭代对象,第二个参数是对应的布尔选择器序列,将可迭代对象中,选择器为True的元素。
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] >>> 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', '1060 W ADDISON', '4801 N BROADWAY']
-
构造字典的子集:
-
字典推导(更快):
p1 = {key: value for key, value in prices.items() if value > 200}
-
将元组序列传递给dict()函数:
p1 = dict((key, value) for key, value in prices.items() if value > 200)
-
-
命名的元组:collections.namedtuple(),支持所有的普通元组的操作,比如索引和解压。
>>> from collections import namedtuple >>> Subscriber = namedtuple('Subscriber', ['addr', 'joined']) >>> sub = Subscriber('jonesy@example.com', '2012-10-19') >>> sub Subscriber(addr='jonesy@example.com', joined='2012-10-19') >>> sub.addr 'jonesy@example.com' >>> sub.joined '2012-10-19' >>>
- 命名元组另一个用途就是作为字典的替代,因为字典需要更多的内存空间,但是缺点是命名元组不可更改,只能使用_replace()方法,创建一个全新的命名元组并替代之前的。
-
转换同时计算数据:生成器表达式。
s = sum((x * x for x in nums)) # 显示的传递一个生成器表达式对象 s = sum(x * x for x in nums) # 更加优雅的实现方式,省略了括号 # min(),max()同理
-
合并字典:collections 模块中的ChainMap 类。
from collections import ChainMap c = ChainMap(a,b) print(c['x']) # Outputs 1 (from a)
-
对于update()来说,他会创建一个新的字典,并且a变化并不会再影响c。而上面的方法是a变化c也会变化,因为他们仅仅是逻辑上合并了为一个,其实还是各是各。
>>> a = {'x': 1, 'z': 3 } >>> b = {'y': 2, 'z': 4 } >>> merged = dict(b) >>> merged.update(a)
-
【Python CookBook】第一章 数据结构和算法
最新推荐文章于 2024-09-04 15:17:01 发布