这是一个基于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
语义。