学习资料的搜集和选择是门大学问,很多人都推荐Python核心编程,然而这书是用Python2写的,学Python3的读起来很难,陆续粗略看过很多书,想找一个进阶的书,《Dive into Python3》其实也不适合当作入门之后的进阶,因为它的例子太少且英文版读起来还是有点吃力。《流畅的Python》则太过于深入语言本身,介绍了很多语言演变过程和一些语法机制的实现等,目标人群也不是我。在V2EX论坛里看到Python区首推的就有《Python Cookbook》,发现真的内容很详实,每一章都以问题切入,探讨一些深入点的语法问题,很适合我。所以打算好好学习这本书,每小结都写一篇博客。
#1.2 解压可迭代对象赋值给多个变量 grades = [55,76,88,91,45] first,*mid,last = grades print(mid) # 1.3 保留最后n个元素 from collections import deque def search(lines,pattern,history=5): pre_lines = deque(maxlen=history) for line in lines: if pattern in line: yield line,pre_lines pre_lines.append(line) print(line,pre_lines) lines = ''' hello jack how you doing ha hah hahaha ''' t = search(lines,'ha') for i in t: print(i) # 1.4 查找最大或者最小的n个元素 import heapq nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2] print(heapq.nlargest(3,nums)) print(heapq.nsmallest(3,nums)) 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']) print(cheap) # heapify堆排序 nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2] heapq.heapify(nums) print(nums) print(heapq.heappop(nums)) # 弹出最小三个元素 print(heapq.heappop(nums)) print(heapq.heappop(nums)) # 1.5 实现一个优先级队列 class ProprityQueue: 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 = ProprityQueue() q.push(Item('foo'),1) q.push(Item('bar'),5) q.push(Item('bar2'),5) print(q.pop()) # 1.6字典中的键映射多个值 defaultdict from collections import defaultdict d = defaultdict(list) d['a'].append(1) d['a'].append(2) d['b'].append(4) print(d) d = defaultdict(set) d['a'].add(1) d['a'].add(2) d['b'].add(4) print(d) d = {} # 类型是字典而不是集合 print(type(d)) d.setdefault('a',[]).append(1) d.setdefault('b',[]).append(2) print(d) # 简化设置一键多值 d = {'a':[1,2,3],'b':[3,4]} pairs = {'a':[5,6,7],'b':[7,8,9]} for k,v in pairs.items(): d[k].append(v) # 结果{'a': [1, 2, 3, 5, 6, 7], 'b': [3, 4, 7, 8, 9]},append则结果是{'a': [1, 2, 3, [5, 6, 7]], 'b': [3, 4, [7, 8, 9]]} print(d) # 1.7 字典排序 OrderedDict # 1.8 字典的运算 prices = { 'ACME': 45.23, 'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.20, 'FB': 10.75 } def f(k): return prices[k] t = min(prices,key=f) print(t) # FB,是键 t = min(zip(prices.values(),prices.keys())) print(t) # (10.75, 'FB') # 1.9 查找两字典的相同点 a = { 'x' : 1, 'y' : 2, 'z' : 3 } b = { 'w' : 10, 'x' : 11, 'y' : 2 } print(a.keys() & b.keys()) print(a.keys() - b.keys()) # 1.10 删除序列相同元素并保持顺序 def dedupe(items,key=None): # 该函数的实现模仿了sorted(),min(),max()等内置函数 seen = set() for item in items: val = item if key is None else key(item) if val not in seen: yield val # yield val可实现返回字典的值 yield item # yield item可以实现返回字典的键(lambda函数的返回值排序) seen.add(item) a = [1,5,2,1,9,5,10,2] t = list(dedupe(a)) print(t) t = list(dedupe(prices,key=lambda k:prices[k])) print(t) # 1.11 命名切片 s1 = slice(20,23) s2 = slice(31,37) record = '....................100 .......513.25 ..........' print(record[s1]) print(record[s2]) print(int(record[s1])*float(record[s2])) print(s1.start,s1.step,s1.stop) s = 'HelloWorld' # s.indices(len(s)) # 错误!py3字符串没有indices方法 # 1.12 找出序列中出现次数最多的元素 from collections import Counter 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' ] word_counts = Counter(words) print(word_counts) # Counter类型,继承自dict # 1.13 通过某个关键字排序一个字典列表 from operator import 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}, {'fname': 'Brian', 'lname': 'Ross', 'uid': 1005}, ] t = sorted(rows,key=itemgetter('uid')) print(t) # 1.14 排序不支持原生比较的对象 key=user.id # 1.15 通过某个字段将记录分组 from itertools import groupby rows.sort(key=itemgetter('fname')) t = groupby(rows,key=itemgetter('fname')) # 返回迭代器 for date,items in t: print(date,items) # 1.16 过滤序列元素 mylist = [1, 4, -5, 10, -7, 2, 3, -1] g = (n for n in mylist if n>0) for i in g: print(i) g = (n if n >0 else abs(n) for n in mylist) for i in g: print(i) # 较复杂的过滤规则 mylist = [1, 4, -5, 10, -7,'a','N/A', 2, 3, -1] def is_int(val): try: x = int(val) return True except ValueError: return False result = list(filter(is_int,mylist)) print(result) # itertools.compress() ,它以一个 iterable对象和一个相对应的 Boolean 选择器序列作为输入参数。然后输出 iterable 对象中对 # 应选择器为 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] print(more5) print(list(compress(addresses,more5))) # filter和compress比较:filter第二个参数是函数,compress第二个参数是布尔选择器序列 # 1.17 从字典中提取子集 prices = { 'ACME': 45.23, 'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.20, 'FB': 10.75 } # 创建一个元组序列再传给dict,可以完成和字典推导一样的功能 TODO 生成器和迭代器 t = ((k,v) for k,v in prices.items() if v>100) print(type(t)) for i in t: print(i) for i in t: print(i) print(dict(t)) # 1.18 映射名称到序列元素 # 想通过名称来访问元素。 from collections import namedtuple Subscriber = namedtuple('Subscriber',['addr','joined']) sub = Subscriber('jonesy@163.com','2012-10-19') print(sub,type(sub)) print(sub.addr) # 1.19 转换并同时计算数据 # 使用生成器表达式作为计算函数的参数。 nums = [1,3,2,4] s1 = sum(x**2 for x in nums) s2 = sum((x**2 for x in nums)) print(s1,s2) # 1.20 合并多个字典或映射 a = {'x': 1, 'z': 3 } b = {'y': 2, 'z': 4 } from collections import ChainMap c = ChainMap(a,b) print(c['x']) print(c['y']) print(c)# ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4}) # 如果出现重复键,那么第一次出现的映射值会被返回