【Python Cookbook学习笔记】 第一章 数据结构和算法

学习资料的搜集和选择是门大学问,很多人都推荐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})
# 如果出现重复键,那么第一次出现的映射值会被返回
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值