首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

collections

2.4版本中的新功能。

这个模块实现专门的容器数据类型提供替代Python的通用内置容器中,dictlistset,和tuple

namedtuple()

工厂函数用于创建具有命名字段的元组子类

2.6版本中的新功能。

带有快速追加和两端弹出的类列表容器

2.4版本中的新功能。

计数器

dict用于计算可哈希对象的子类

2.7版本的新功能。

OrderedDict

字典子类,记录添加的订单条目

2.7版本的新功能。

defaultdict

dict调用工厂函数以提供缺失值的子类

2.5版本中的新功能。

除了具体的容器类之外,集合模块还提供抽象基类,可用于测试某个类是否提供了特定的接口,例如,它是可哈希还是映射。

1.计数器对象

提供计数器工具以支持方便快捷的计数。例如:

代码语言:javascript
复制
>>> # Tally occurrences of words in a list
>>> cnt = Counter()
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
...     cnt[word] += 1
>>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1})

>>> # Find the ten most common words in Hamlet
>>> import re
>>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
 ('you', 554),  ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]

class collections.Counter([iterable-or-mapping])

A Counterdict用于计算可哈希对象的子类。它是一个无序的集合,其元素以字典键的形式存储,并将其计数存储为字典值。计数允许为包括零或负计数的任何整数值。该Counter课程类似于其他语言的书包或多媒体课程。

元素从一个迭代中计数或从另一个映射(或计数器)初始化:

代码语言:javascript
复制
>>> c = Counter()                           # a new, empty counter
>>> c = Counter('gallahad')                 # a new counter from an iterable
>>> c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
>>> c = Counter(cats=4, dogs=8)             # a new counter from keyword args

计数器对象有一个字典界面,只不过它们会为丢失的项目返回零计数,而不是引发KeyError

代码语言:javascript
复制
>>> c = Counter(['eggs', 'ham'])
>>> c['bacon']                              # count of a missing element is zero
0

将计数设置为零不会从计数器中删除元素。使用del完全删除它:

代码语言:javascript
复制
>>> c['sausage'] = 0                        # counter entry with a zero count
>>> del c['sausage']                        # del actually removes the entry

2.7版本的新功能。

Counter对象支持超出所有字典可用的三种方法:

elements()

将元素返回一个迭代器,每次重复的次数与它的次数相同。元素以任意顺序返回。如果一个元素的数量少于一个,elements()将忽略它。

代码语言:javascript
复制
>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> list(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']

most_common([n])

从最常见到最不常见的列表中,列出n个最常见的元素及其数量。如果省略nNone,则most_common()返回计数器中的所有元素。具有相同计数的元素可以任意排序:

代码语言:javascript
复制
>>> Counter('abracadabra').most_common(3)
[('a', 5), ('r', 2), ('b', 2)]

subtract([iterable-or-mapping])

元素从可迭代或从另一个映射(或计数器)中减去。像dict.update()但减去计数而不是替换它们。输入和输出都可以是零或负数。

代码语言:javascript
复制
>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> d = Counter(a=1, b=2, c=3, d=4)
>>> c.subtract(d)
>>> c
Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})

通常的字典方法可用于Counter对象,但对于计数器的工作方式不同。

fromkeys(iterable)

这个类方法没有为Counter对象实现。

update([iterable-or-mapping])

元素从一个迭代中计数或从另一个映射(或计数器)加入。像dict.update()但增加了计数而不是替换它们。此外,可迭代预计是一系列元素,而不是一系列(key, value)对。

处理Counter对象的常见模式:

代码语言:javascript
复制
sum(c.values())                 # total of all counts
c.clear()                       # reset all counts
list(c)                         # list unique elements
set(c)                          # convert to a set
dict(c)                         # convert to a regular dictionary
c.items()                       # convert to a list of (elem, cnt) pairs
Counter(dict(list_of_pairs))    # convert from a list of (elem, cnt) pairs
c.most_common()[:-n-1:-1]       # n least common elements
c += Counter()                  # remove zero and negative counts

提供了几个数学运算来组合Counter对象以产生多集(具有大于零的计数的计数器)。加法和减法通过加或减相应元素的计数来组合计数器。相交和联合会返回相应计数的最小值和最大值。每个操作都可以接受带符号计数的输入,但输出将排除计数为零或更小的结果。

代码语言:javascript
复制
>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d                       # add two counters together:  c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>> c - d                       # subtract (keeping only positive counts)
Counter({'a': 2})
>>> c & d                       # intersection:  min(c[x], d[x])
Counter({'a': 1, 'b': 1})
>>> c | d                       # union:  max(c[x], d[x])
Counter({'a': 3, 'b': 2})

注意

计数器主要设计为用积极整数来表示运行计数; 但是,注意不要不必要地排除需要其他类型或负值的用例。为了帮助解决这些用例,本节介绍了最小范围和类型限制。

  • Counter类本身是一本字典的子类,在其键和值没有任何限制。这些值旨在表示计数的数字,但您可以在值字段中存储任何内容。
  • most_common()方法只要求值是可订购的。
  • 对于就地操作,例如c[key] += 1,值类型只需要支持加法和减法。所以分数,浮点数和小数将会起作用并且负值被支持。同样也是如此update(),并subtract()允许负和用于输入和输出的零个值。
  • multiset方法仅用于具有正值的用例。输入可能为负值或零,但只能创建正值的输出。没有类型限制,但值类型需要支持加法,减法和比较。
  • elements()方法需要整数计数。它忽略零和负数。

2.对象和

class collections.deque([iterable[, maxlen]])

使用append()来自iterable的数据从左到右地初始化(使用)返回一个新的deque对象。如果未指定迭代,则新的双端队列为空。

Deques是堆栈和队列的泛化(名称发音为“deck”,是“双端队列”的缩写)。Deques支持线程安全,高效的内存追加,并从双侧出现,并且在任一方向都具有大致相同的O(1)性能。

尽管list对象支持类似的操作,但它们针对快速固定长度操作进行了优化,并且会产生O(n)内存移动成本pop(0)insert(0, v)操作,这些成本会改变底层数据表示的大小和位置。

2.4版本中的新功能。

如果未指定maxlenNonedeque,则deques可能增长到任意长度。否则,deque被限制到指定的最大长度。一旦有限长度的deque已满,当添加新项目时,相应数量的项目将从相反的一端被丢弃。有界长度deques提供的功能类似于tailUnix中的过滤器。它们也可用于跟踪只有最近的活动感兴趣的交易和其他数据池。

在版本2.6中更改:添加了maxlen参数。

Deque对象支持以下方法:

append(x)

x添加到双端队列的右侧。

appendleft(x)

x添加到双端队列的左侧。

clear()

删除deque中的所有元素,使其长度为0。

count(x)

计算deque元素的数量等于x

2.7版本的新功能。

extend(iterable)

通过追加iterable参数中的元素来扩展双端队列的右侧。

extendleft(iterable)

通过附加iterable中的元素来扩展双端队列的左侧。请注意,一系列左边附加结果颠倒了迭代参数中元素的顺序。

pop()

从deque的右侧移除并返回一个元素。如果没有元素存在,则引发一个IndexError

popleft()

从deque的左侧移除并返回一个元素。如果没有元素存在,则引发一个IndexError

remove(value)

删除了第一次出现的。如果找不到,就提出一个ValueError

2.5版本中的新功能。

reverse()

在原地颠倒deque的元素,然后返回None

2.7版本的新功能。

rotate(n)

向右旋转deque n个步骤。如果n为负数,则向左旋转。向右旋转一步相当于:d.appendleft(d.pop())

Deque对象还提供一个只读属性:

maxlen

一个deque的最大大小或者None是否是无限的。

2.7版本的新功能。

除上述外,双端支持迭代,酸洗,len(d)reversed(d)copy.copy(d)copy.deepcopy(d),会员与测试in操作,并标引用,如d[-1]。索引访问在两端都是O(1),但在中间减慢到O(n)。对于快速随机访问,请使用列表。

例:

代码语言:javascript
复制
>>> from collections import deque
>>> d = deque('ghi')                 # make a new deque with three items
>>> for elem in d:                   # iterate over the deque's elements
...     print elem.upper()
G
H
I

>>> d.append('j')                    # add a new entry to the right side
>>> d.appendleft('f')                # add a new entry to the left side
>>> d                                # show the representation of the deque
deque(['f', 'g', 'h', 'i', 'j'])

>>> d.pop()                          # return and remove the rightmost item
'j'
>>> d.popleft()                      # return and remove the leftmost item
'f'
>>> list(d)                          # list the contents of the deque
['g', 'h', 'i']
>>> d[0]                             # peek at leftmost item
'g'
>>> d[-1]                            # peek at rightmost item
'i'

>>> list(reversed(d))                # list the contents of a deque in reverse
['i', 'h', 'g']
>>> 'h' in d                         # search the deque
True
>>> d.extend('jkl')                  # add multiple elements at once
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
>>> d.rotate(1)                      # right rotation
>>> d
deque(['l', 'g', 'h', 'i', 'j', 'k'])
>>> d.rotate(-1)                     # left rotation
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])

>>> deque(reversed(d))               # make a new deque in reverse order
deque(['l', 'k', 'j', 'i', 'h', 'g'])
>>> d.clear()                        # empty the deque
>>> d.pop()                          # cannot pop from an empty deque
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in -toplevel-
    d.pop()
IndexError: pop from an empty deque

>>> d.extendleft('abc')              # extendleft() reverses the input order
>>> d
deque(['c', 'b', 'a'])

2.1. deque Recipes

本节介绍与deques合作的各种方法。

有界长度的deques提供了类似于tailUnix中的过滤器的功能:

代码语言:javascript
复制
def tail(filename, n=10):
    'Return the last n lines of a file'
    return deque(open(filename), n)

另一种使用deques的方法是通过附加到右边并弹出到左边来维护一系列最近添加的元素:

代码语言:javascript
复制
def moving_average(iterable, n=3):
    # moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0
    # http://en.wikipedia.org/wiki/Moving_average
    it = iter(iterable)
    d = deque(itertools.islice(it, n-1))
    d.appendleft(0)
    s = sum(d)
    for elem in it:
        s += elem - d.popleft()
        d.append(elem)
        yield s / float(n)

rotate()方法提供了一种实现deque切片和删除的方法。例如,一个纯粹的Python实现del d[n]依赖于该rotate()方法来定位要弹出的元素:

代码语言:javascript
复制
def delete_nth(d, n):
    d.rotate(-n)
    d.popleft()
    d.rotate(n)

要实施deque切片,请使用类似的方法rotate()来将目标元素放置在双侧的左侧。删除旧条目popleft(),添加新条目extend(),然后反转。随着对这种做法的微小变化,很容易实现第四风格栈操作,如dupdropswapoverpickrot,和roll

3. defaultdict对象

class collections.defaultdict([default_factory[, ...]])

返回一个新的类似字典的对象。defaultdict是内置类的一个子dict类。它覆盖一个方法并添加一个可写实例变量。其余的功能与dict该类相同,不在此处记载。

第一个参数提供了default_factory属性的初始值; 它默认为None。所有其余参数的处理方式与将它们传递给dict构造函数(包括关键字参数)相同。

2.5版本中的新功能。

defaultdict除了标准dict操作外,对象还支持以下方法:

__missing__(key)

如果该default_factory属性是None,则会引发一个KeyError为参数的异常。

如果default_factory不是None,则调用不带参数来为给定提供默认值,将此值插入到的字典中并返回。

如果调用default_factory引发异常,则此异常将传播不变。

当未找到请求的密钥时,该__getitem__()方法由dict类的方法调用; 无论它返回还是提出,然后返回或提出__getitem__()

请注意,__missing__()要求任何操作之外__getitem__()。这意味着get(),与普通字典一样,它将None作为默认返回而不是使用default_factory

defaultdict 对象支持以下实例变量:

default_factory

该属性被该__missing__()方法使用; 它从第一个参数初始化到构造函数,如果存在的话,或者None如果没有的话。

3.1。defaultdict例子

使用list这种方式default_factory,很容易将一系列键值对组合成一个列表字典:

代码语言:javascript
复制
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

当第一次遇到每个密钥时,它不在映射中; 所以使用default_factory返回空的函数自动创建一个条目listlist.append()然后该操作将该值附加到新列表中。当再次遇到密钥时,查找正常进行(返回该密钥的列表),并且该list.append()操作向列表添加另一个值。这种技术比使用dict.setdefault()以下技术的等效技术更简单快捷:

代码语言:javascript
复制
>>> d = {}
>>> for k, v in s:
...     d.setdefault(k, []).append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

设置default_factoryint使defaultdict有用的计数(如其他语言包或多重集):

代码语言:javascript
复制
>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
...     d[k] += 1
...
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]

当第一次遇到字母时,它从映射中丢失,所以default_factory函数调用int()默认计数为零。增量操作然后为每个字母建立计数。

int()总是返回零的函数只是常数函数的特例。创建常量函数的更快更灵活的方法是使用itertools.repeat()哪个可以提供任何常量值(而不仅仅是零):

代码语言:javascript
复制
>>> def constant_factory(value):
...     return itertools.repeat(value).next
>>> d = defaultdict(constant_factory('<missing>'))
>>> d.update(name='John', action='ran')
>>> '%(name)s %(action)s to %(object)s' % d
'John ran to <missing>'

设置default_factoryset使defaultdict建立集合的字典有用:

代码语言:javascript
复制
>>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
>>> d = defaultdict(set)
>>> for k, v in s:
...     d[k].add(v)
...
>>> d.items()
[('blue', set([2, 4])), ('red', set([1, 3]))]

4.具有命名字段的元组的namedtuple()库函数

命名元组赋予元组中每个位置的含义并允许更具可读性的自编写代码。它们可以在任何使用常规元组的地方使用,并且可以通过名称而不是位置索引来添加字段。

collections.namedtuple(typename, field_names[, verbose=False][, rename=False])

返回一个名为typename的新的元组子类。新的子类用于创建具有可通过属性查找访问的字段的类似元组的对象,以及可索引和可??迭代的对象。子类的实例也有一个有用的docstring(带有typename和field_names)和一个有用的__repr__()方法,它以一种name=value格式列出元组内容。

FIELD_NAMES是字符串如序列['x', 'y']。或者,field_names可以是单个字符串,每个字段名用空格和/或逗号分隔,例如'x y''x, y'

任何有效的Python标识符都可以用于字段名称,除了以下划线开头的名称。有效标识符由字母,数字和下划线,但不以数字或下划线开始,不能是keyword诸如回报全球传递打印,或提高

如果重命名为true,则无效的字段名会自动替换为位置名称。例如,['abc', 'def', 'ghi', 'abc']转换为['abc', '_1', 'ghi', '_3'],消除关键字def和重复的字段名称abc

如果verbose为true,则在构建之前打印类定义。

命名元组实例没有每个实例字典,因此它们是轻量级的,并且不需要比常规元组更多的内存。

2.6版本中的新功能。

在版本2.7中更改:增加了对重命名的支持。

例:

代码语言:javascript
复制
>>> Point = namedtuple('Point', ['x', 'y'], verbose=True)
class Point(tuple):
    'Point(x, y)'

    __slots__ = ()

    _fields = ('x', 'y')

    def __new__(_cls, x, y):
        'Create new instance of Point(x, y)'
        return _tuple.__new__(_cls, (x, y))

    @classmethod
    def _make(cls, iterable, new=tuple.__new__, len=len):
        'Make a new Point object from a sequence or iterable'
        result = new(cls, iterable)
        if len(result) != 2:
            raise TypeError('Expected 2 arguments, got %d' % len(result))
        return result

    def __repr__(self):
        'Return a nicely formatted representation string'
        return 'Point(x=%r, y=%r)' % self

    def _asdict(self):
        'Return a new OrderedDict which maps field names to their values'
        return OrderedDict(zip(self._fields, self))

    def _replace(_self, **kwds):
        'Return a new Point object replacing specified fields with new values'
        result = _self._make(map(kwds.pop, ('x', 'y'), _self))
        if kwds:
            raise ValueError('Got unexpected field names: %r' % kwds.keys())
        return result

    def __getnewargs__(self):
        'Return self as a plain tuple.  Used by copy and pickle.'
        return tuple(self)

    __dict__ = _property(_asdict)

    def __getstate__(self):
        'Exclude the OrderedDict from pickling'
        pass

    x = _property(_itemgetter(0), doc='Alias for field number 0')

    y = _property(_itemgetter(1), doc='Alias for field number 1')



>>> p = Point(11, y=22)     # instantiate with positional or keyword arguments
>>> p[0] + p[1]             # indexable like the plain tuple (11, 22)
33
>>> x, y = p                # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y               # fields also accessible by name
33
>>> p                       # readable __repr__ with a name=value style
Point(x=11, y=22)

命名元组对于将字段名称分配给由csvsqlite3模块返回的结果元组特别有用:

代码语言:javascript
复制
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')

import csv
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
    print emp.name, emp.title

import sqlite3
conn = sqlite3.connect('/companydata')
cursor = conn.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
for emp in map(EmployeeRecord._make, cursor.fetchall()):
    print emp.name, emp.title

除了从元组继承的方法之外,命名元组还支持三个附加方法和一个属性。为防止与字段名冲突,方法和属性名称以下划线开头。

classmethod somenamedtuple._make(iterable)

从现有序列创建新实例或迭代的类方法。

代码语言:javascript
复制
>>> t = [11, 22]
>>> Point._make(t)
Point(x=11, y=22)

somenamedtuple._asdict()

返回一个新的OrderedDict映射字段名称到它们相应的值:

代码语言:javascript
复制
>>> p = Point(x=11, y=22)
>>> p._asdict()
OrderedDict([('x', 11), ('y', 22)])

在版本2.7中更改:返回OrderedDict而不是常规dict

somenamedtuple._replace(kwargs)

返回指定元组的新实例,用新值替换指定字段:

代码语言:javascript
复制
>>> p = Point(x=11, y=22)
>>> p._replace(x=33)
Point(x=33, y=22)

>>> for partnum, record in inventory.items():
...     inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())

somenamedtuple._fields

列出字段名称的字符串元组。用于内省和从现有命名元组中创建新的命名元组类型。

代码语言:javascript
复制
>>> p._fields            # view the field names
('x', 'y')

>>> Color = namedtuple('Color', 'red green blue')
>>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)
>>> Pixel(11, 22, 128, 255, 0)
Pixel(x=11, y=22, red=128, green=255, blue=0)

要检索名称存储在字符串中的字段,请使用以下getattr()函数:

代码语言:javascript
复制
>>> getattr(p, 'x')
11

要将字典转换为命名元组,请使用双星运算符(如解包参数列表中所述):

代码语言:javascript
复制
>>> d = {'x': 11, 'y': 22}
>>> Point(**d)
Point(x=11, y=22)

由于命名元组是一个常规的Python类,因此使用子类很容易添加或更改功能。以下是如何添加计算字段和固定宽度的打印格式:

代码语言:javascript
复制
>>> class Point(namedtuple('Point', 'x y')):
...     __slots__ = ()
...     @property
...     def hypot(self):
...         return (self.x ** 2 + self.y ** 2) ** 0.5
...     def __str__(self):
...         return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)
...
>>> for p in Point(3, 4), Point(14, 5/7.):
...     print p
Point: x= 3.000  y= 4.000  hypot= 5.000
Point: x=14.000  y= 0.714  hypot=14.018

上面显示的子类设置__slots__为空元组。这有助于通过防止创建实例字典来降低内存需求。

子类化对于添加新的存储字段没有用处。相反,只需从_fields属性创建一个新的命名元组类型:

代码语言:javascript
复制
>>> Point3D = namedtuple('Point3D', Point._fields + ('z',))

默认值可以通过使用_replace()定制原型实例来实现:

代码语言:javascript
复制
>>> Account = namedtuple('Account', 'owner balance transaction_count')
>>> default_account = Account('<owner name>', 0.0, 0)
>>> johns_account = default_account._replace(owner='John')

枚举常量可以使用命名元组来实现,但使用简单的类声明更简单,更高效:

代码语言:javascript
复制
>>> Status = namedtuple('Status', 'open pending closed')._make(range(3))
>>> Status.open, Status.pending, Status.closed
(0, 1, 2)
>>> class Status:
...     open, pending, closed = range(3)

5. OrderedDict对象

有序字典就像普通字典一样,但他们记得插入项目的顺序。在迭代有序字典时,将按照首次添加密钥的顺序返回项目。

class collections.OrderedDict([items])

返回一个字典子类的实例,支持通常的dict方法。一个OrderedDict是记住的键首先被插入的顺序的字典。如果新条目覆盖现有条目,则原始插入位置保持不变。删除一个条目并重新插入它将会把它移到最后。

2.7版本的新功能。

OrderedDict.popitem(last=True)

popitem()有序字典的方法返回并删除(键,值)对。如果最后一个为真,则按LIFO顺序返回对,否则按FIFO顺序返回。

除了通常的映射方法外,有序字典还支持使用反向迭代reversed()

OrderedDict对象之间的平等测试是顺序敏感的,并按照实现list(od1.items())==list(od2.items())OrderedDict对象和其他Mapping对象之间的平等测试与常规字典一样对命令不敏感。这允许OrderedDict在使用常规字典的任何地方替换对象。

OrderedDict构造函数和update()方法都接受关键字参数,但他们的订单丢失,因为Python的函数调用语义传递在使用普通无序字典关键字参数。

5.1. OrderedDict Examples and Recipes

由于有序字典会记住它的插入顺序,因此它可以与排序结合使用以创建一个排序后的字典:

代码语言:javascript
复制
>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}

>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])

删除条目时,新排序的字典会保持排序顺序。但是,当添加新的密钥时,密钥被追加到最后,并且不保持排序。

创建一个有序的字典变体也是直接的,可以记住键最后插入的顺序。如果新条目覆盖现有条目,则会更改原始插入位置并移至最后:

代码语言:javascript
复制
class LastUpdatedOrderedDict(OrderedDict):
    'Store items in the order the keys were last added'

    def __setitem__(self, key, value):
        if key in self:
            del self[key]
        OrderedDict.__setitem__(self, key, value)

一个有序的字典可以和这个Counter类结合起来,这样计数器就能记住第一次遇到的顺序元素:

代码语言:javascript
复制
class OrderedCounter(Counter, OrderedDict):
     'Counter that remembers the order elements are first encountered'

     def __repr__(self):
         return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))

     def __reduce__(self):
         return self.__class__, (OrderedDict(self),)

6.集合抽象基类

收藏模块提供了以下ABC

ABC

继承

抽象方法

混合方法

容器

?

__contains__

?

可哈希

?

__hash__

?

可迭代

?

__iter__

?

迭代器

可迭代

下一个

__iter__

大小

?

__len__

?

可赎回

?

__呼叫__

?

序列

大小,Iterable,容器

__getitem__,__len__

__contains__,__iter__,__reversed__,索引和计数

MutableSequence

序列

__getitem__,__setitem__,__delitem__,__len__,insert

继承序列方法并附加,反向,扩展,弹出,删除和__iadd__

大小,Iterable,容器

__contains__,__iter__,__len__

__le__,__lt__,__eq__,__ne__,__gt__,__ge__,__and__,__or__,__sub__,__xor__和isdisjoint

MutableSet

__contains__,__iter__,__len__,添加,放弃

继承Set方法和clear,pop,remove,__ior__,__iand__,__ixor__和__isub__

制图

大小,Iterable,容器

__getitem__,__iter__,__len__

__contains__,键,项目,值,get,__eq__和__ne__

MutableMapping

制图

__getitem__,__setitem__,__delitem__,__iter__,__len__

继承的映射方法和pop,popitem,clear,update和setdefault

MappingView

大小

?

__len__

ItemsView

MappingView,Set

?

__contains__,__iter__

KeysView

MappingView,Set

?

__contains__,__iter__

ValuesView

MappingView

?

__contains__,__iter__

class collections.Containerclass collections.Hashableclass collections.Sizedclass collections.Callable

对于类的ABC分别提供的方法__contains__()__hash__()__len__(),和__call__()

class collections.Iterable

ABC提供了该__iter__()方法的类。另请参阅iterable的定义。

class collections.Iterator

ABC提供的类__iter__()next()方法。另请参阅迭代器的定义。

class collections.Sequenceclass collections.MutableSequence

ABCs为只读和可变序列

class collections.Setclass collections.MutableSet

用于只读和可变集的ABCs。

class collections.Mappingclass collections.MutableMapping

ABCs为只读和可变映射

class collections.MappingViewclass collections.ItemsViewclass collections.KeysViewclass collections.ValuesView

用于映射的ABCs,项目,键和值视图

这些ABCs允许我们询问类或实例是否提供特定的功能,例如:

代码语言:javascript
复制
size = None
if isinstance(myvar, collections.Sized):
    size = len(myvar)

一些ABCs也可以用作mixin,从而更容易开发支持容器API的类。例如,写支撑满类Set的API,它仅需要提供三个底层抽象方法:__contains__()__iter__(),和__len__()。ABC提供其余的方法,如__and__()isdisjoint()

代码语言:javascript
复制
class ListBasedSet(collections.Set):
     ''' Alternate set implementation favoring space over speed
         and not requiring the set elements to be hashable. '''
     def __init__(self, iterable):
         self.elements = lst = []
         for value in iterable:
             if value not in lst:
                 lst.append(value)

     def __iter__(self):
         return iter(self.elements)

     def __contains__(self, value):
         return value in self.elements

     def __len__(self):
         return len(self.elements)

s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
overlap = s1 & s2            # The __and__() method is supported automatically

关于使用SetMutableSet作为mixin的注意事项:

  • 由于某些集合操作会创建新集合,因此默认的mixin方法需要通过迭代来创建新实例。假设类构造函数在表单中有一个签名ClassName(iterable)。这个假设因素等,以所谓的内部类方法_from_iterable()这就要求cls(iterable)制作了一套新的。如果Setmixin在具有不同构造函数签名的类中使用,则需要_from_iterable()用可以从可迭代参数构造新实例的类方法重写。
  • 要覆盖比较(据推测为速度,因为语义是固定的),重新定义__le__()__ge__(),则其他操作会自动效仿。
  • Set混入提供了一种_hash()计算用于该组的散列值的方法; 然而,__hash__()没有定义,因为并不是所有的集合都是可散列的或不可变的。要使用混入添加集hashability,来自继承Set()Hashable(),然后再定义__hash__ = Set._hash

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com