setutils
- IndexedSet
类型¶
这个 set
类型将集合论的实际表现力带到了Python中。它总体上有一个非常丰富的API,但缺乏几个基本功能。首先,套餐是不订购的。最重要的是,集合是不可索引的,即, my_set[8]
将引发一个 TypeError
。这个 IndexedSet
类型解决了这两个问题,而不会影响到Python的内置Set实现的优秀复杂性特征。
- class boltons.setutils.IndexedSet(other=None)[源代码]¶
IndexedSet
是一种collections.MutableSet
以保持插入元素的插入顺序和唯一性。它是一种混合类型,主要类似于OrderedSet,但也list
-Like,因为它支持索引和切片。- 参数:
other (iterable) -- 用于初始化集的可选迭代器。
>>> x = IndexedSet(list(range(4)) + list(range(8))) >>> x IndexedSet([0, 1, 2, 3, 4, 5, 6, 7]) >>> x - set(range(2)) IndexedSet([2, 3, 4, 5, 6, 7]) >>> x[-1] 7 >>> fcr = IndexedSet('freecreditreport.com') >>> ''.join(fcr[:fcr.index('.')]) 'frecditpo'
标准集运算符与互操作
set
均受支持:>>> fcr & set('cash4gold.com') IndexedSet(['c', 'd', 'o', '.', 'm'])
如您所见,
IndexedSet
几乎就像是一个UniqueList
,只保留给定值的一个副本,按其第一次添加的顺序。对于好奇的人来说,IndexedSet不支持基于索引设置项的原因(即,__setitem__()
),考虑以下两难境地:my_indexed_set = [A, B, C, D] my_indexed_set[2] = A
在这一点上,一个集合只需要一个 A ,而是一个
list
将覆盖 C 。覆盖 C 会改变列表的长度,这意味着my_indexed_set[2]
不会是 A ,与预期的列表一样,但更确切地说 D 。所以,不__setitem__()
。
- boltons.setutils.complement(wrapped)[源代码]¶
给出了一个
set
,将其转换为 complement set 。鉴于A
set
跟踪它包含的内容,一个 complement set 跟踪它做了什么 not 包围圈。例如,看看当我们将正常集与补集相交时会发生什么:>>> list(set(range(5)) & complement(set([2, 3])))
[0, 1, 4]
我们得到左边不在右边的所有东西,因为与补码相交等同于减去一个正常集。
- 参数:
wrapped (set) -- 应变为补集的集合或任何其它可迭代的集合。
所有集合方法和运算符都受补集支持,在其他
complement()
-套装和/或常规套装set
物体。因为补集只跟踪元素是什么 not 在SET中,基于SET内容的功能不可用:
len()
,iter()
(和循环),以及.pop()
。但补集总是可以通过再次补集来变回常规集:>>> s = set(range(5)) >>> complement(complement(s)) == s True
备注
空的补集对应于 universal set 来自数学。
集合的许多用法可以通过补语更简单地表示出来。你不需要在脑子里想出正确的方法来颠倒一个表达,你只需在集合中抛出一个补语即可。考虑以下名称筛选器的示例:
>>> class NamesFilter(object): ... def __init__(self, allowed): ... self._allowed = allowed ... ... def filter(self, names): ... return [name for name in names if name in self._allowed] >>> NamesFilter(set(['alice', 'bob'])).filter(['alice', 'bob', 'carol']) ['alice', 'bob']
如果我们只是想表达“让所有的名字都通过”呢?
我们可以尝试列举所有预期的名称::
``NamesFilter({'alice', 'bob', 'carol'})``
但这是非常脆弱的--如果在某个点上将此对象更改为滤镜怎么办
['alice', 'bob', 'carol', 'dan']
?更糟糕的是,接下来处理这段代码的可怜的程序员怎么办?他们不知道这个庞大的允许集的目的是“允许一切”,还是因为某种微妙的原因而将“Dan”排除在外。
补语集让程序员的意图被简洁而直接地表达出来:
NamesFilter(complement(set()))
这段代码不仅简短且健壮,而且其意图也很容易理解。