首页 > 解决方案 > freezesets 的“Multiton”实现 - 每个值只有一个实例

问题描述

我怎样才能实现frozensets 的 Multiton 设计模式,无论它frozenset是如何创建的?

我正在寻找的是行为就像 的类frozenset,但它保证“完全实习”:对于任何两个实例,如果a == bthen a is b

这个问题的答案似乎为传递给构造函数的每个参数 生成了一个实例(并且似乎还假设这些是可散列的)。但是一个给定的frozenset可以用许多不同的方式构造:构造函数可以得到具有不同元素顺序的元组,或者不可散列的列表;或者您可以使用诸如 a.union(b) 之类的运算符来创建冻结集等。

动机自然是 - 试图节省内存。我有一个图,其中许多顶点由(除其他外)recurring frozensets 标记。该图是通过从旧的顶点创建新的顶点来“增长”的,而新frozenset的 s 是通过从旧的顶点中添加或删除元素来获得的。

非常感谢!

标签: pythondesign-patternsfactoryfrozensetmultiton

解决方案


这是一种可能的解决方案。

class Uniquifier(object) :
    """
    This class accepts an immutable object and returns a "canonical" instance of it, if one exists, or keeps it in store as that canonical instance. This is used as a kind of clunky multiton implementation.

    Of course instances are not destroyed until this object is destroyed.
    """
    def __init__(self):
        self._universe = {}


    def uniquify(self, item):
        try :
            return self._universe[item]
        except KeyError :
            self._universe[item] = item
            return self._universe[item]

运行这个:

a = frozenset([3,5])
b = frozenset([5,3])
c = frozenset([3]).union([5])
print a==b, b==c
print a is b, b is c, a is c

结果是:

True True
False False False

但是这个:

universe = Uniquifier()
a = universe.uniquify(frozenset([3,5]))
b = universe.uniquify(frozenset([5,3]))
c = universe.uniquify(frozenset([3]).union([5]))
print a == b, b==c
print a is b, b is c, a is c

True True
True True True

如预期的。

我希望使用一些 pythonic 魔法可以将 Uniquifier 逻辑“隐藏在幕后”,但我想这具有简单透明的优点。


推荐阅读