python cookbook第三版学习笔记 一
数据结构
假设有M个元素的列表,需要从中分解出N个对象,N<M,这会导致分解的值过多的异常。如下:
record=['zhf','zhf@163.com','775-555-1212','847-555-1212']
name,email,=record
E:\python2.7.11\python.exe E:/py_prj/python_cookbook.py
Traceback (most recent call last):
File "E:/py_prj/python_cookbook.py", line 9, in <module>
name,email,=record
ValueError: too many values to unpack
提示too many values to unpack
在python3中可以用*表达式来解决
record=['zhf','zhf@163.com','775-555-1212','847-555-1212']
name,email,*phone_number=record
此时name=’zhf’,email=’zhf@163.com’
Phone_number=['775-555-1212','847-555-1212']
但是此类用法仅限于3.0. 2.7.6版本会报错
(二)
保存最后N个元素:
有的时候我们希望保存查找到元素的最后前5个元素,比如文件有如下内容:
This is a c test
This is a java test
This is a go test
This is a c++ test
This is a mysql test
This is a javascript test
This is a perl test
This is a ruby test
This is a python test
This is a essamble test
This is a linux test
我们想找到This is a python test的前5个记录。我们可以用collections.deque来实现。 Deque(maxlen=N)创建了一个固定长度的队列,当有新记录加入队列而队列已满时会自动移除最老的记录。实现FIFO的功能。实现代码如下:
def search(lines,pattern,history=5):
#创建一个长度为5的队列
previous_line=deque(maxlen=history)
for line in lines:
if pattern in line:
yield line,previous_line
#将查找到pattern之前的信息插入队列
previous_line.append(line) if __name__=='__main__':
f=open(r'E:\py_prj\test.txt')
for line,previous in search(f,'python',5):
for plines in previous:
#打印出最后5条信息
print plines
#打印出查找到的pattern
print line
结果如下:previous保存了This is a python test的前5条信息
E:\python2.7.11\python.exe E:/py_prj/python_cookbook.py
This is a c++ test
This is a mysql test
This is a javascript test
This is a perl test
This is a ruby test
This is a python test
下面的例子更直观的表现了deque的功能,当达到最大数量的时候,删除最早的元素,然后在末端插入新的元素
>>> from collections import deque
>>> 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)
如果不指定大小,那么则是无限大的队列,可以appendleft在左端插入元素,也可以用popleft来将最左边的出队列
>>> q=deque()
>>> q.append(1)
>>> q.append(2)
>>> q.append(3)
>>> q.appendleft(4)
>>> q
deque([4, 1, 2, 3])
>>> q.popleft()
4
三 找到最大的N个元素:
Heapq模块有2个函数,nlargest()和nsmallest()可以解决这个问题
import heapq
nums=[1,8,2,10,4,5,6,19,20]
largest=heapq.nlargest(3,nums)
print largest
得到结果:
[20, 19, 10]
[1, 2, 4]
我们还可以导入更复杂的数据结构进行比较:如下面的结构。里面包含了6个元素,都是字典类型的。如何根据price对他们进行排序呢
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}
]
我们来看下heapq.nlargest的帮助手册。原型函数中第一个参数是返回的数目,第二个参数表明是可迭代对象。第三个参数key值默认为None
Help on function nlargest in module heapq:
nlargest(n, iterable, key=None)
Find the n largest elements in a dataset.
Equivalent to: sorted(iterable, key=key, reverse=True)[:n]
这个key值和sorted的key值是一个作用,这个key值指定可迭代对象中的一个元素来进行排序。也就是从第二个参数中接受一个参数进行处理,最后得到一个元素。函数会根据这个元素来进行排序。那么前面的例子中,每个迭代对象返回一个字典。那么key值的作用就是从这个字典中取出一个关键参数作为排序的参考。
代码改造如下:使用lambda来实现这个函数功能。这个s值就是portfolio中返回的每个字典值。取出其中price字段进行排序
largest=heapq.nlargest(3,portfolio,key=lambda s:s['price'])
samllest=heapq.nsmallest(3,portfolio,key=lambda s:s['price'])
结果如下:
[{'price': 543.22, 'name': 'AAPL', 'shares': 50}, {'price': 115.65, 'name': 'ACME', 'shares': 75}, {'price': 91.1, 'name': 'IBM', 'shares': 100}]
[{'price': 16.35, 'name': 'YHOO', 'shares': 45}, {'price': 21.09, 'name': 'FB', 'shares': 200}, {'price': 31.75, 'name': 'HPQ', 'shares': 35}]
通过heapq的名字可以看出,这是将一个数据对象用堆排序并取得最大最小的值。具体是如何来实现的呢。我们首先来看下heapq.heapify这个函数
nums=[1,8,2,10,4,5,6,19,20]
heapq.heapify(nums)
print nums
结果如下:
[1, 4, 2, 10, 8, 5, 6, 19, 20]
其实heapfify就是生成一个最小堆的树型结构。具体最小堆的定义可以参考数据结构。最小堆就是子节点大于父节点。结构如下所示:
1,8,2,10,4,5,6,19,20的树形结构如下
1
8 2
10 4 5 6
19 20
排序后的数据结构,可以看到变动仅在于8和4,也就是将4上浮,8下沉。得到如下的结构。可以看到最顶端的父节点始终是最小的元素。
1
4 2
10 8 5 6
19 20
因此根据这个结构我们就可以用heapq.heappop(nums)得到最小的元素。其实每次heappop执行的过程都是一次堆重新排序的过程,自动将最小的元素排在父节点。整个执行过程如下:
>>> nums=[1,8,2,10,4,5,6,19,20]
#首先必须要用heapify将数据转换成堆的形式
>>> heapq.heapify(nums)
>>> nums
[1, 4, 2, 10, 8, 5, 6, 19, 20]
1
4 2
10 8 5 6
19 20
>>> heapq.heappop(nums)
1
>>> nums
[2, 4, 5, 10, 8, 20, 6, 19]
2
4 5
10 8 20 6
19
>>> heapq.heappop(nums)
2
>>> nums
[4, 8, 5, 10, 19, 20, 6]
4
8 5
10 19 20 6
>>> heapq.heappop(nums)
4
>>> nums
[5, 8, 6, 10, 19, 20]
5
8 6
10 19 20
>>> heapq.heappop(nums)
5
>>> nums
[6, 8, 20, 10, 19]
6
8 20
10 19
>>> heapq.heappop(nums)
6
>>> nums
[8, 10, 20, 19]
8
10 20
19
>>> heapq.heappop(nums)
8
>>> nums
[10, 19, 20]
10
19 20
>>> heapq.heappop(nums)
10
>>> nums
[19, 20]
19
20
>>> heapq.heappop(nums)
19
>>> nums
[20]
从上面的过程可以看到,其实每次heappop都是一次树型结构的调整,自动会将最小的元素上浮到父节点,
上浮和下沉的具体实现函数如下,有兴趣的可以研究下。
def _siftup(heap, pos):
endpos = len(heap)
startpos = pos
newitem = heap[pos]
# Bubble up the smaller child until hitting a leaf.
childpos = 2*pos + 1 # leftmost child position
while childpos < endpos:
# Set childpos to index of smaller child.
rightpos = childpos + 1
if rightpos < endpos and not cmp_lt(heap[childpos], heap[rightpos]):
childpos = rightpos
# Move the smaller child up.
heap[pos] = heap[childpos]
pos = childpos
childpos = 2*pos + 1
# The leaf at pos is empty now. Put newitem there, and bubble it up
# to its final resting place (by sifting its parents down).
heap[pos] = newitem
_siftdown(heap, startpos, pos)
python cookbook第三版学习笔记 一的更多相关文章
- python cookbook第三版学习笔记十:类和对象(一)
类和对象: 我们经常会对打印一个对象来得到对象的某些信息. class pair: def __init__(self,x,y): self.x=x self. ...
- python cookbook第三版学习笔记六:迭代器与生成器
假如我们有一个列表 items=[1,2,3].我们要遍历这个列表我们会用下面的方式 For i in items: Print i 首先介绍几个概念:容器,可迭代对象,迭代器 容器是一种存储数据 ...
- python cookbook第三版学习笔记十三:类和对象(三)描述器
__get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...
- python cookbook第三版学习笔记二十:可自定义属性的装饰器
在开始本节之前,首先介绍下偏函数partial.首先借助help来看下partial的定义 首先来说下第一行解释的意思: partial 一共有三个部分: (1)第一部分也就是第一个参数,是一个函数, ...
- python cookbook第三版学习笔记十六:抽象基类
假设一个工程中有多个类,每个类都通过__init__来初始化参数.但是可能有很多高度重复且样式相同的__init__.为了减少代码.我们可以将初始化数据结构的步骤归纳到一个单独的__init__函数中 ...
- python cookbook第三版学习笔记十五:property和描述
8.5 私有属性: 在python中,如果想将私有数据封装到类的实例上,有两种方法:1 单下划线.2 双下划线 1 单下划线一般认为是内部实现,但是如果想从外部访问的话也是可以的 2 双下划线是则无法 ...
- python cookbook第三版学习笔记七:python解析csv,json,xml文件
CSV文件读取: Csv文件格式如下:分别有2行三列. 访问代码如下: f=open(r'E:\py_prj\test.csv','rb') f_csv=csv.reader(f) for f in ...
- python cookbook第三版学习笔记十三:类和对象(四)描述器
__get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...
- python cookbook第三版学习笔记十一:类和对象(二)调用父类的方法
在子类中调用父类的方法,可以下面的A.spam(self)的方法. class A(object): def spam(self): print 'A.spam' class ...
随机推荐
- #include<> 和#include“”的区别
1.< >引用的是编译器的类库路径里面的头文件2." "引用的是程序目录的相对路径中的头文件,在程序目录的相对路径中找不到该头文件时会继续在类库路径里搜寻该头文件 ...
- lightoj1336数论基础
#include<iostream> #include<cstdio> #include<cmath> #define ll long long using nam ...
- 为什么要用Handler ?
我的理解,Handler的好处之一就是配合子线程处理数据之后控制UI的显示. 如下是http://www.cnblogs.com/sydeveloper/p/3312865.html的完美解释: 当应 ...
- 关于cisco ccp 或sdm管理gns3中思科路由器的成功分享
本来工作环境中有一台c1841,闲来无事,升级了最新的IOS=c1841-adventerprisek9-mz.151-4.M6.bin,在xp虚拟机中安装sdm(新windows系统不支持)和在wi ...
- 智能指针剖析(下)boost::shared_ptr&其他
1. boost::shared_ptr 前面我已经讲解了两个比较简单的智能指针,它们都有各自的优缺点.由于 boost::scoped_ptr 独享所有权,当我们真真需要复制智能指针时,需求便满足不 ...
- Oracle 12C 新特性之表分区带 异步全局索引异步维护(一次add、truncate、drop、spilt、merge多个分区)
实验准备:-- 创建实验表CREATE TABLE p_andy(ID number(10), NAME varchar2(40))PARTITION BY RANGE (id)(PARTITION ...
- 华硕 F1A55-M LX3系列跳线图
天啊,第一次遇到这么变态的主板跳线...浪费我好久时间找到这跳线图
- HiveHbase集成实践
作者:Syn良子 出处:http://www.cnblogs.com/cssdongl/p/6857891.html 转载请注明出处 简单的说就是可以通过Hive SQL直接对hbase的表进行读写操 ...
- hexo从零开始到搭建完整
前言 其实平时自己写的文章并不多,偶尔看到一些东西会做点笔记,但是每次写的东西都会到处放,不好找,所以才想着自己搭建一个人博客网站,现在大家用hexo比较多,也比较方便,并且能使用的主题也很多,所以小 ...
- Bootstrap学习笔记之文本对齐风格
文本对齐风格 在排版中离不开文本的对齐方式.在CSS中常常使用text-align来实现文本的对齐风格的设置.其中主要有四种风格: ☑ 左对齐,取值left ☑ 居中对齐,取值center ☑ ...