这是一个基于id -> object地图的实现(由@nmclean建议)和collections.MutableSet:
from collections import MutableSet
class IdentitySet(MutableSet):
key = id # should return a hashable object
def __init__(self, iterable=()):
self.map = {} # id -> object
self |= iterable # add elements from iterable to the set (union)
def __len__(self): # Sized
return len(self.map)
def __iter__(self): # Iterable
return self.map.itervalues()
def __contains__(self, x): # Container
return self.key(x) in self.map
def add(self, value): # MutableSet
"""Add an element."""
self.map[self.key(value)] = value
def discard(self, value): # MutableSet
"""Remove an element. Do not raise an exception if absent."""
self.map.pop(self.key(value), None)
def __repr__(self):
if not self:
return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, list(self))
例子:
a = (1, 2)
print IdentitySet([a, (1, 2), a])
# -> IdentitySet([(1, 2), (1, 2)]) # only one instance of `a`
print s != Set([a, (1, 2), a]) # it might be unequal because new literal
# tuple (1, 2) might have a different id
print s | Set([a, (1, 2), a])
# -> IdentitySet([(1, 2), (1, 2), (1, 2)]) # `a` plus two tuples from literals
MutableSet自动提供方法:clear, pop, remove, __ior__, __iand__, __ixor__, __isub__, __le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__, __sub__, __xor__, 和isdisjoint.
在这里,与set基于 in 的实现不同,复合操作总是使用覆盖的基本方法,例如|( self.__or__(), union) 是根据 来实现的self.add(),因此它提供了正确的IdentitySet语义。