zoukankan      html  css  js  c++  java
  • Python标准库之Collections---Container datatype

    Deques

    Deques,即 Double-ended-queues,是支持线程安全,内存高效的列表类对象。Deques是可改变的,支持索引等类似于list的操作,然而,我们不能直接对Deques进行切片操作。

    from collections import deque
    
    dq=deque('abcde')
    
    dq[1:2] #不能直接对Deques进行切片操作
    
    ---------------------------------------------------------------------------
    
    TypeError                                 Traceback (most recent call last)
    
    <ipython-input-3-15d291305198> in <module>()
    ----> 1 dq[1:2] #不能直接对Deques进行切片操作
    
    
    TypeError: sequence index must be integer, not 'slice'
    

    与list相比,Deques的最大的优点就是在deque的开始插入比list在开端的插入更快,尽管deque在末尾插入比list在末尾插入要略微慢些。deque是线程安全的,所以可以用pickle来序列化。

    li=['a','b']
    li.extend('ef');li
    
    ['a', 'b', 'e', 'f']
    
    li.extend(['de']);li
    
    ['a', 'b', 'e', 'f', 'de']
    

    一种有效的思考Deques的方法就是通过扩充和消耗列表项,Deques可以从两端进行扩充/消耗列表项。

    dq=deque('abc')
    dq.append('d');dq
    
    deque(['a', 'b', 'c', 'd'])
    
    dq.appendleft('z');dq
    
    deque(['z', 'a', 'b', 'c', 'd'])
    
    dq.extend('eft');dq
    
    deque(['z', 'a', 'b', 'c', 'd', 'e', 'f', 't'])
    
    dq.extendleft('yxw');dq
    
    deque(['w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 't'])
    

    我们可以用pop()popleft()来消耗deque:

    dq.pop()
    
    't'
    
    dq
    
    deque(['w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f'])
    
    dq.popleft()
    
    'w'
    
    dq
    
    deque(['x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f'])
    

    我们可以使用rotate(n)方法来把最后/最前n项移到最前/最后(n是正数,则是把最后n项移到最前)

    dq.rotate(2);dq
    
    deque(['e', 'f', 'x', 'y', 'z', 'a', 'b', 'c', 'd'])
    
    dq.rotate(-2)
    
    dq
    
    deque(['x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f'])
    

    既然我们不能直接对deque进行切片,那么我们可以通过itertools.slice来间接进行切片操作:

    import itertools
    
    list(itertools.islice(dq,3,9))
    
    ['a', 'b', 'c', 'd', 'e', 'f']
    
    dq
    
    deque(['x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f'])
    

    另一个非常有意思的特性是,Deques支持maxlen选项,该选项限制了deque的最大长度,这使得它非常适合做一个叫循环缓冲器Circular Buffer)的数据结构:

    dq2=deque([],maxlen=3)
    for i in range(6):
        dq2.append(i)
        print(dq2)
    
    deque([0], maxlen=3)
    deque([0, 1], maxlen=3)
    deque([0, 1, 2], maxlen=3)
    deque([1, 2, 3], maxlen=3)
    deque([2, 3, 4], maxlen=3)
    deque([3, 4, 5], maxlen=3)
    

    ChainMaps

    collections.ChainMap是在Python3.2被加入的,它提供了一种链接多个字典的方法,因此它们可以被是做一个对象!ChainMapmaps属性,new_child()方法,parents属性。我们可以用maps[i]来获取到第i个字典,用parents属性获取它的所有“父类”,尽管字典本身无序,ChainMaps却是一个有序列表字典。

    ChainMap在我们用了很多相互关联的字典时候,是非常有用的。它的消耗是遵从优先等级的,先消耗相同关键字的出现在前面的字典的值。

    from collections import ChainMap
    
    defaults={'theme':'Default','language':'eng','showIndex':True,'showFooter':True}
    
    cm=ChainMap(defaults)
    
    cm
    
    ChainMap({'theme': 'Default', 'language': 'eng', 'showIndex': True, 'showFooter': True})
    
    cm2=cm.new_child({'theme':'blusky'})
    
    cm2['theme']
    
    'blusky'
    
    cm2['showFooter']
    
    True
    
    cm3=cm.new_child({'johnyang':'Yes'})
    
    cm3
    
    ChainMap({'johnyang': 'Yes'}, {'theme': 'Default', 'language': 'eng', 'showIndex': True, 'showFooter': True})
    
    cm2.pop('theme')
    
    'blusky'
    
    cm2['theme']
    
    'Default'
    
    cm2['theme']
    
    'Default'
    
    cm2
    
    ChainMap({}, {'theme': 'Default', 'language': 'eng', 'showIndex': True, 'showFooter': True})
    
    cm3
    
    ChainMap({'johnyang': 'Yes'}, {'theme': 'Default', 'language': 'eng', 'showIndex': True, 'showFooter': True})
    
    cm4=cm.new_child({'theme':'johnyang'})
    
    cm5=cm4.new_child({'showIndex':False})
    
    cm5 #该处可以清楚的看到ChainMap链接了多个字典!
    
    ChainMap({'showIndex': False}, {'theme': 'johnyang'}, {'theme': 'Default', 'language': 'eng', 'showIndex': True, 'showFooter': True})
    
    cm5.maps[1]
    
    {'theme': 'johnyang'}
    
    cm5.maps[-1]
    
    {'theme': 'Default', 'language': 'eng', 'showIndex': True, 'showFooter': True}
    
    cm5.parents
    
    ChainMap({'theme': 'johnyang'}, {'theme': 'Default', 'language': 'eng', 'showIndex': True, 'showFooter': True})
    

    ChainMap的优点在于它不仅仅只是一个字典,而是还保存了之前的值,添加一个子字典,覆盖了之前相同关键字对应的值,但是它并没有将之前的关键字的值移除,这样当我们需要保留更改的记录,就可以很容易的回滚到之前的状态。

    cm5
    
    ChainMap({'showIndex': False}, {'theme': 'johnyang'}, {'theme': 'Default', 'language': 'eng', 'showIndex': True, 'showFooter': True})
    
    cm5.maps[0]={'change?':'Yes'}
    
    cm5
    
    ChainMap({'change?': 'Yes'}, {'theme': 'johnyang'}, {'theme': 'Default', 'language': 'eng', 'showIndex': True, 'showFooter': True})
    

    Counter

    Counter 是字典的子类,该子类下,每个字典关键字是一个可哈希的对象,与之相应的是该对象出现次数的数字,有三种方法来初始化:(1)序列,(2)Key:value键值对 (3) (object=value,...)

    from collections import Counter
    
    Counter('anysequence')
    
    Counter({'a': 1, 'n': 2, 'y': 1, 's': 1, 'e': 3, 'q': 1, 'u': 1, 'c': 1})
    
    c1=Counter('anyseequence')
    c2=Counter({'a':1,'c':1,'e':3})
    c3=Counter(a=1,c=1,e=3)
    
    c1
    
    Counter({'a': 1, 'n': 2, 'y': 1, 's': 1, 'e': 4, 'q': 1, 'u': 1, 'c': 1})
    
    c2
    
    Counter({'a': 1, 'c': 1, 'e': 3})
    
    c3
    
    Counter({'a': 1, 'c': 1, 'e': 3})
    
    Counter([(1,2),(3,4),(5,6),(5,6)])
    
    Counter({(1, 2): 1, (3, 4): 1, (5, 6): 2})
    
    Counter([[1,2],[3,4]]) #列表不可哈希,所以报错
    
    ---------------------------------------------------------------------------
    
    TypeError                                 Traceback (most recent call last)
    
    <ipython-input-59-7de62ba7f6e6> in <module>()
    ----> 1 Counter([[1,2],[3,4]])
    
    
    D:anacondalibcollections\__init__.py in __init__(*args, **kwds)
        564             raise TypeError('expected at most 1 arguments, got %d' % len(args))
        565         super(Counter, self).__init__()
    --> 566         self.update(*args, **kwds)
        567 
        568     def __missing__(self, key):
    
    
    D:anacondalibcollections\__init__.py in update(*args, **kwds)
        651                     super(Counter, self).update(iterable) # fast path when counter is empty
        652             else:
    --> 653                 _count_elements(self, iterable)
        654         if kwds:
        655             self.update(kwds)
    
    
    TypeError: unhashable type: 'list'
    

    我们也可以创建一个空counter对象,然后通过update方法来填充它:

    ct=Counter()
    
    ct.update('abca');ct
    
    Counter({'a': 2, 'b': 1, 'c': 1})
    
    ct.update({'a':3})
    
    ct
    
    Counter({'a': 5, 'b': 1, 'c': 1})
    
    ct.update('def')
    
    ct
    
    Counter({'a': 5, 'b': 1, 'c': 1, 'd': 1, 'e': 1, 'f': 1})
    
    ct.update('aaaa')
    
    ct
    
    Counter({'a': 9, 'b': 1, 'c': 1, 'd': 1, 'e': 1, 'f': 1})
    

    Counter对象与字典最大的不同在于counter对于缺失项返回0,而字典报错。

    ct['a']
    
    9
    
    ct['johnyang']
    
    0
    
    ct
    
    Counter({'a': 9, 'b': 1, 'c': 1, 'd': 1, 'e': 1, 'f': 1})
    
    ct.update({'a':-3,'b':-2,'d':3,'e':2})
    
    ct
    
    Counter({'a': 6, 'b': -1, 'c': 1, 'd': 4, 'e': 3, 'f': 1})
    

    可以用elements()方法来返回一个由Counter对象产生的迭代器,该迭代器不包含count值小于1的项,并且是乱序的。

    sorted(ct.elements())
    
    ['a', 'a', 'a', 'a', 'a', 'a', 'c', 'd', 'd', 'd', 'd', 'e', 'e', 'e', 'f']
    

    另外两个值得一提的方法是most_common()subtract()

    ct.most_common()
    
    [('a', 6), ('d', 4), ('e', 3), ('c', 1), ('f', 1), ('b', -1)]
    
    ct.subtract({'a':2})
    
    ct
    
    Counter({'a': 4, 'b': -1, 'c': 1, 'd': 4, 'e': 3, 'f': 1})
    

    Ordered Dictionaries

    有序字典的重要性在于它们能记住插入的顺序,所以当遍历它们时候,它们能以被插入的顺序来返回值。而对于普通字典,它们的键值对的顺序是随意的,当我们测试两个字典是否相等时,仅仅考察的是它们的键值对是否一一对应,而没有考虑它们插入的顺序是否也一样,而有序字典则不然,它们除了考虑键值对是否一一对应,还考虑插入顺序是否一致。

    from collections import OrderedDict
    
    od1=OrderedDict()
    od1['one']=1
    od1['two']=2
    od2=OrderedDict()
    od2['two']=2
    od2['one']=1
    
    
    od1
    
    OrderedDict([('one', 1), ('two', 2)])
    
    od2
    
    OrderedDict([('two', 2), ('one', 1)])
    
    od1==od2
    
    False
    
    a=dict(ok=1,yes=2)
    b=dict(yes=2,ok=1)
    a==b
    
    True
    

    当我们用update方法来从list中增加值时候,有序字典将会保持它们在list中的顺序。

    kvs=[('three',3),('four',4),('fivee',5),('six',6)]
    od1.update(kvs)
    for k,v in od1.items():print(k,v)
    
    one 1
    two 2
    three 3
    four 4
    fivee 5
    six 6
    

    defaultdict

    defaultdict也是dict的子类,它为字典的初始化提供了一个便利的方法。对于普通字典,当索取一个不存在的键时候,Python将会抛出一个KeyError错误,而defaultdict不会,它将会用default_factory参数给出个默认初始值。

    from collections import defaultdict
    
    dd=defaultdict(int)
    
    words=str.split('red blue green red yellow blue red green green red')
    
    for word in words:dd[word]+=1
    
    dd
    
    defaultdict(int, {'red': 4, 'blue': 2, 'green': 3, 'yellow': 1})
    
    def isprimary(c):
        if (c=='red') or (c=='blue') or (c=='green'):
            return True
        else:
            return False
    
    dd2=defaultdict(bool)
    
    for word in words:dd2[word]=isprimary(word)
    
    dd2
    
    defaultdict(bool, {'red': True, 'blue': True, 'green': True, 'yellow': False})
    

    Named Tuples

    from collections import namedtuple
    
    space=namedtuple('space','x y z')
    
    s1=space(x=2,y=4,z=10)
    
    s1.x*s1.y*s1.z # 计算体积
    
    80
    
    space2=namedtuple('space2','x def z',rename=True)
    
    s1=space2(3,4,5)
    
    s1.z
    
    5
    
    s1._1
    
    4
    

    named tuple有它自己的3个方法:_make(),_asdict(),_replace(),这些方法都以下划线开头,来防止与field name冲突(本例子中是'space'),_make()将可迭代对象作为输入参数,把它变成named tuple:

    sl=[4,5,6]
    sl=space._make(sl)
    
    sl
    
    space(x=4, y=5, z=6)
    

    _asdict()返回一个OrderedDict对象:

    sl._asdict()
    
    OrderedDict([('x', 4), ('y', 5), ('z', 6)])
    

    _replace()方法返回一个新的实例,将标明的值替换:

    sl._replace(x=7,z=9)
    
    space(x=7, y=5, z=9)
    
    
    
    ##### 愿你一寸一寸地攻城略地,一点一点地焕然一新 #####
  • 相关阅读:
    设置DataGridView垂直滚动条
    在自定义MessageBox控件里添加键盘回车事件。
    通过访问注册表,表判断系统是否装excel
    让文本框里只能输入数字
    新晋菜鸟的错误
    jdbc连接数据库以及crud(简单易懂,本人亲测可用 有源代码和数据库)
    springboot 错误求解决
    maven 导包报错
    最短路径Dijkstra
    读写者问题
  • 原文地址:https://www.cnblogs.com/johnyang/p/14702584.html
Copyright © 2011-2022 走看看