<p>可以使用<code>__new__</code>方法在<code>frozenset</code>周围创建包装器。我引用<a href="https://docs.python.org/3/reference/datamodel.html#object.__new__" rel="nofollow noreferrer">the doc</a>:</p>
<blockquote>
<p><strong>new</strong>() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.</p>
</blockquote>
<p>其思想是缓存创建的每个包装,并始终为相同的<code>frozenset</code>返回相同的实例。你知道吗</p>
<p>有一个小技巧:<code>frozenset</code>的元素本身就是<code>frozenset</code>,它们也应该被包装。你知道吗</p>
<pre><code>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
</code></pre>
<p>示例:</p>
<pre><code>f1 = FrozenSetWrapper([1,2,3])
f2 = FrozenSetWrapper([1,2,3])
print(f1, f2)
# <__main__.FrozenSetWrapper object at 0x7f7894f2fa90> <__main__.FrozenSetWrapper object at 0x7f7894f2fa90>
</code></pre>
<p>现在,我们必须重新实现<code>frozenset</code>的方法来获得一个完美的匹配。这对他们中的一些人来说很容易:只需将工作委托给包装的<code>frozenset</code>:</p>
<pre><code>def __repr__(self):
return self._fs.__repr__()
def __iter__(self):
return self._fs.__iter__()
...
</code></pre>
<p>但是对于某些方法,必须处理<code>frozenset</code>和<code>FrozenSetWrapper</code>:</p>
<pre><code>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
...
</code></pre>
<p>或返回类型:</p>
<pre><code>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) ...")
</code></pre>
<p>实习的想法是有道理的,但实施起来可能会很棘手,因为边缘的情况。你知道吗</p>