Python程序设计开发宝典
上QQ阅读APP看书,第一时间看更新

3.6 标准库中的其他常用数据类型

除了大量内置数据类型,Python还通过collections、enum、array、heapq、fractions等标准库提供了其他丰富的类型。

3.6.1 枚举类型

        >>>from enum import Enum                   #导入模块中的类
        >>>class Color(Enum):                      #创建自定义枚举类
            red=1
            blue=2
            green=3
        >>>Color.red                               #访问枚举类的成员
        <Color.red: 1>
        >>>type(Color.green)                       #查看枚举类成员的类型
        <enum'Color'>
        >>>isinstance(Color.red, Color)
        True
        >>>x=dict()
        >>>x[Color.red]='red'                      #枚举类成员可哈希,可以作为字典的“键”
        >>>x
        {<Color.red: 1>: 'red'}
        >>>Color(2)                                #返回指定值对应的枚举类成员
        <Color.blue: 2> 
        >>>Color['red']
        <Color.red: 1>
        >>>r=Color.red
        >>>r.name
        'red'
        >>>r.value
        1
        >>>list(Color)                             #枚举类是可以迭代的
        [<Color.red: 1>, <Color.blue: 2>, <Color.green: 3>]

3.6.2 数组类型

标准库array提供的array类支持数组的创建与使用,可以创建的数组类型包括整数、实数、Unicode字符等,可以使用help()函数查看更完整的类型列表。

        >>>from array import array
        >>>s="Hello world"
        >>>sa=array('u', s)                         #创建可变字符串对象
        >>>print(sa)
        array('u', 'Hello world')
        >>>print(sa.tostring())                     #查看可变字符串对象内容
        b'H\x00e\x00l\x00l\x00o\x00\x00w\x00o\x00r\x00l\x00d\x00'
        >>>print(sa.tounicode())                    #查看可变字符串对象内容
        Hello world
        >>>sa[0]='F'                                #修改指定位置上的字符
        >>>print(sa) 
        array('u', 'Fello world')
        >>>sa.insert(5, 'w')                        #在指定位置插入字符
        >>>print(sa)
        array('u', 'Fellow world')
        >>>sa.remove('l')                           #删除指定字符的首次出现
        >>>print(sa)
        array('u', 'Felow world')
        >>>sa.remove('w')
        >>>print(sa)
        array('u', 'Felo world')
        >>>ia=array('I')                            #创建整型数组
        >>>for i in range(5):
            ia.append(i)
        >>>ia
        array('I', [0,1,2,3,4])
        >>>ia[0]=5
        >>>ia
        array('I', [5,1,2,3,4])

3.6.3 队列

Python标准库queue提供了LILO队列类Queue、LIFO队列类LifoQueue、优先级队列类PriorityQueue,标准库collections提供了双端队列。例如:

        >>>from queue import Queue                #LILO队列
        >>>q=Queue()                              #创建队列对象
        >>>q.put(0)                               #在队列尾部插入元素
        >>>q.put(1)
        >>>q.put(2)
        >>>print(q.queue)                         #查看队列中的所有元素
        deque([0,1,2])
        >>>q.get()                                #返回并删除队列的头部元素
        0
        >>>q.get()
        1
        >>>q.get()
        2

        >>>from queue import LifoQueue            #LIFO队列
        >>>q=LifoQueue()                          #创建LIFO队列对象
        >>>q.put(1)                               #在队列尾部插入元素
        >>>q.put(2)
        >>>q.put(3)
        >>>q.queue                                #查看队列中的所有元素
        [1,2,3]
        >>>q.get()                                #返回并删除队列尾部元素
        3
        >>>q.get()
        2
        >>>q.queue
        [1]
        >>>q.get()                                #对空队列调用get()方法会阻塞当前线程
        >>>from queue import PriorityQueue        #优先级队列
        >>>q=PriorityQueue()                      #创建优先级队列对象
        >>>q.put(3)                               #插入元素
        >>>q.put(8)                               #插入元素
        >>>q.put(100)
        >>>q.queue                                #查看优先级队列中的所有元素
        [3,8,100]
        >>>q.put(1)                               #插入元素,自动调整优先级队列
        >>>q.put(2)
        >>>q.queue
        [1,2,100,8,3]
        >>>q.get()                                #返回并删除优先级最低的元素
        1
        >>>q.get()                                #多执行几次该语句并观察返回的数据
        2

        >>>from collections import deque
        >>>q=deque(maxlen=5)                      #创建双端队列
        >>>for item in [3,5,7,9,11]:              #添加元素
            q.append(item)
        >>>q.append(13)                           #队列满,自动溢出
        >>>q.append(15)
        >>>q
        deque([7,9,11,13,15], maxlen=5)
        >>>q.appendleft(5)                        #从左侧添加元素,右侧自动溢出
        >>>q
        deque([5,7,9,11,13], maxlen=5)
        >>>q.popleft()                            #弹出并返回最左端元素
        5
        >>>q.pop()                                #弹出并返回最右端元素
        13
        >>>q
        deque([7,9,11], maxlen=5)
        >>>q.insert(2,10)                         #在中间位置插入元素
        >>>q
        deque([7,9,10,11], maxlen=5)
        >>>q+=[1,2]                               #追加多个元素
        >>>q
        deque([9,10,11,1,2], maxlen=5)
        >>>q.pop()
        2
        >>>q.pop()
        1
        >>>q
        deque([9,10,11], maxlen=5)
        >>>q*=2                                   #序列重复
        >>>q
        deque([10,11,9,10,11], maxlen=5)
        >>>q.count(10)                            #返回元素的出现次数
        2
        >>>q.rotate(2)                            #循环右移2个元素
        >>>q
        deque([10,11,10,11,9], maxlen=5)
        >>>q.rotate(-2)                           #循环左移2个元素
        >>>q
        deque([10,11,9,10,11], maxlen=5)

3.6.4 具名元组

        >>>from collections import namedtuple
        >>>Point=namedtuple('Point', ['x', 'y', 'z'])     #创建具名元组类
        >>>Point
        <class'__main__.Point'>
        >>>p=Point(3,4,5)                                 #实例化对象
        >>>p
        Point(x=3, y=4, z=5) 
        >>>p.x                                            #访问成员
        3
        >>>p._fields                                      #查看字段列表
        ('x', 'y', 'z')
        >>>p._replace(x=30, z=8)                          #替换成员值,返回新对象
        Point(x=30, y=4, z=8)
        >>>p.x=7                                          #不允许这样直接赋值
        AttributeError: can't set attribute
        >>>d=dict()
        >>>d[p]='spirit position'                         #具名元组对象可以作为字典的“键”
        >>>d
        {Point(x=3, y=4, z=5): 'spirit position'}

3.6.5 堆

堆是一个特殊的二叉树,其中每个父节点的值都小于或等于其所有子节点的值。使用数组或列表来实现小根堆时,对于所有的k(下标,从0开始)都满足heap[k]<=heap[2*k+1]和heap[k]<= heap[2*k+2],并且整个堆中最小的元素总是位于二叉树的根节点,大根堆与小根堆正好相反。Python在heapq模块中提供了对堆的支持。

    >>>import heapq                                #导入heapq模块
    >>>import random
    >>>data=random.sample(range(1000),10)          #生成随机测试数据
    >>>data
    [638,659,212,84,737,677,553,340,526,747]
    >>>heapq.heapify(data)                         #堆化随机测试数据
    >>>data
    [84,340,212,526,737,677,553,659,638,747]
    >>>heapq.heappush(data,30)                     #新元素入堆,自动调整堆结构
    >>>data
    [30,84,212,526,340,677,553,659,638,747,737]
    >>>heapq.heappush(data,5)
    >>>data
    [5,84,30,526,340,212,553,659,638,747,737,677]
    >>>heapq.heappop(data)                         #返回并删除最小元素,自动调整堆
    5
    >>>heapq.heappop(data)
    30
    >>>heapq.heappop(data)
    84
    >>>data
    [212,340,553,526,737,677,747,659,638]
    >>>heapq.heappushpop(data,1000)                #弹出最小元素,同时新元素入堆
    212
    >>>data
    [340,526,553,638,737,677,747,659,1000]
    >>>heapq.heapreplace(data,500)                 #弹出最小元素,同时新元素入堆
    340
    >>>data
    [500,526,553,638,737,677,747,659,1000]
    >>>heapq.heapreplace(data,700)
    500
    >>>data
    [526,638,553,659,737,677,747,700,1000]
    >>>heapq.nlargest(3, data)                     #返回最大的前3个元素
    [1000,747,737]
    >>>heapq.nsmallest(2, data, key=str)           #返回指定排序规则下最小的2个元素
    [1000,526]