您可以使用该__new__
方法在frozenset
. 我引用文档:
new () 主要是为了允许不可变类型(如 int、str 或 tuple)的子类自定义实例创建。它也通常在自定义元类中被覆盖,以自定义类创建。
这个想法是缓存创建的每个包装器,并始终为相同的frozenset
.
有一个小技巧:frozenset
那些本身就是frozenset
s 的元素,它们也应该被包裹起来。
class FrozenSetWrapper:
_cache = {}
def __new__(cls, iterable=[]):
fs = frozenset(FrozenSetWrapper(e) if isinstance(e, frozenset) else e
for e in iterable) # wrap recursively
fsw = FrozenSetWrapper._cache.get(fs)
if fsw is None: # was not in cache
fsw = super(FrozenSetWrapper, cls).__new__(cls) # create an object
fsw._fs = fs # init
fsw.__doc__ = fs.__doc__
FrozenSetWrapper._cache[fs] = fsw # cache
return fsw # and return
例子:
f1 = FrozenSetWrapper([1,2,3])
f2 = FrozenSetWrapper([1,2,3])
print(f1, f2)
# <__main__.FrozenSetWrapper object at 0x7f7894f2fa90> <__main__.FrozenSetWrapper object at 0x7f7894f2fa90>
现在,我们必须重新实现frozenset
获得完美匹配的方法。这对他们中的一些人来说很容易:只需将工作委托给被包装的frozenset
:
def __repr__(self):
return self._fs.__repr__()
def __iter__(self):
return self._fs.__iter__()
...
但是对于某些方法,您必须处理frozenset
and FrozenSetWrapper
:
def __contains__(self, e):
elif isinstance(e, frozenset):
e = FrozenSetWrapper(e)
return self._fs.contains(e)
def __eq__(self, other):
if isinstance(other, FrozenSetWrapper):
return self is other
elif isinstance(other, frozenset)
return self._fs == other
else:
return False
...
或返回类型:
def __and__(self, other):
if isinstance(other, FrozenSetWrapper):
return FrozenSetWrapper(self._fs.__and__(other._fs))
elif isinstance(other, frozenset):
return FrozenSetWrapper(self._fs.__and__(other))
else:
raise TypeError("unsupported operand type(s) ...")
实习的想法是有道理的,但由于边缘情况,实施可能会很棘手。