数据结构

假设有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第三版学习笔记 一的更多相关文章

  1. python cookbook第三版学习笔记十:类和对象(一)

    类和对象: 我们经常会对打印一个对象来得到对象的某些信息. class pair:     def __init__(self,x,y):         self.x=x         self. ...

  2. python cookbook第三版学习笔记六:迭代器与生成器

    假如我们有一个列表 items=[1,2,3].我们要遍历这个列表我们会用下面的方式 For i in items:   Print i 首先介绍几个概念:容器,可迭代对象,迭代器 容器是一种存储数据 ...

  3. python cookbook第三版学习笔记十三:类和对象(三)描述器

    __get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...

  4. python cookbook第三版学习笔记二十:可自定义属性的装饰器

    在开始本节之前,首先介绍下偏函数partial.首先借助help来看下partial的定义 首先来说下第一行解释的意思: partial 一共有三个部分: (1)第一部分也就是第一个参数,是一个函数, ...

  5. python cookbook第三版学习笔记十六:抽象基类

    假设一个工程中有多个类,每个类都通过__init__来初始化参数.但是可能有很多高度重复且样式相同的__init__.为了减少代码.我们可以将初始化数据结构的步骤归纳到一个单独的__init__函数中 ...

  6. python cookbook第三版学习笔记十五:property和描述

    8.5 私有属性: 在python中,如果想将私有数据封装到类的实例上,有两种方法:1 单下划线.2 双下划线 1 单下划线一般认为是内部实现,但是如果想从外部访问的话也是可以的 2 双下划线是则无法 ...

  7. 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 ...

  8. python cookbook第三版学习笔记十三:类和对象(四)描述器

    __get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...

  9. python cookbook第三版学习笔记十一:类和对象(二)调用父类的方法

    在子类中调用父类的方法,可以下面的A.spam(self)的方法. class A(object):     def spam(self):         print 'A.spam' class ...

随机推荐

  1. MongoDB副本集的常用操作及原理

    本文是对MongoDB副本集常用操作的一个汇总,同时也穿插着介绍了操作背后的原理及注意点. 结合之前的文章:MongoDB副本集的搭建,大家可以在较短的时间内熟悉MongoDB的搭建和管理. 下面的操 ...

  2. js,jQuery和DOM操作的总结(二)

    jQuery的基本操作 (1)遍历键值对和数组 , , , , , ]; $.map(arr, function (ele, index) { alert(ele + '===' + index); ...

  3. Java中实现String.padLeft和String.padRight

    因为习惯了C#中的padLeft和padRight,接触Java后突然失去这两个功能,觉得别扭,就试着实现了这两个方法. Java中String.format()中带有字符串对齐功能如下: Syste ...

  4. 交换机进行VLAN划分

    一个交换机连接两个虚拟局域网(vlan10和vlan20),通过设置交换机,实现同一虚拟局域网内部相互通信,不同虚拟局域网内不能相互通信 (vlan 将整个网络划分多个广播域,vlan主机不受地理位置 ...

  5. 蚂蚁金服新一代数据可视化引擎 G2

    新公司已经呆了一个多月,目前着手一个数据可视化的项目,数据可视化肯定要用到图形库如D3.Highcharts.ECharts.Chart等,经决定我的这个项目用阿里旗下蚂蚁金服所开发的G2图表库. 官 ...

  6. 深入理解Java常用类----String(二)

    上篇介绍了String类的构造器,获取内部属性等方法,最后留下了最常用的局部操作函数没有介绍,本篇将接着上篇内容,从这些最常见的函数的操作说起,看看我们日常经常使用的这些方法的内部是怎么实现的.第一个 ...

  7. javaWeb学习总结(8)- JSP中的九个内置对象(4)

    一.JSP运行原理 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet ...

  8. Lua学习(5)——迭代器与泛型for

    1. 迭代器 2. 泛型for语义 所谓迭代器就是一种可以遍历一种集合中所有元素的机制.在lua中,迭代器通常表示为函数,每调用依次函数就返回集合中的下一个元素.泛型for 内部保存了迭代器函数 实际 ...

  9. Extending sparklyr to Compute Cost for K-means on YARN Cluster with Spark ML Library

    Machine and statistical learning wizards are becoming more eager to perform analysis with Spark MLli ...

  10. UX2内核浏览加速技术纲要

    UX2内核是本人负责主要开发的浏览服务项目,其主要目的是为开发者提供一个简单好用.轻便的网络浏览服务.UX2内核的安卓端是基于WebView进行深度优化的,同时欢迎大家使用这个内核用于app页面或浏览 ...