Python:基于参数的Singleton

时间:2016-08-19 07:59:42

标签: python dictionary arguments singleton hashable

我正在关注此link并尝试制作单身课程。但是,考虑参数(在启动类时传递),以便在参数相同时返回相同的对象。

因此,我不想将类名/类引用存储为dict键,而是希望将传递的参数存储为dict中的键。但是,也可能存在不可用的参数(例如dictset本身)。

存储类参数和类对象映射的最佳方法是什么?这样我就可以返回与参数对应的对象。

非常感谢。

EDIT-1 : 多一点解释。假设有如下课程

class A:
    __metaclass__ == Singleton
    def __init__(arg1, arg2):
        pass

现在,A(1,2)应始终返回相同的对象。但是,它应该与A(3,4)

不同

我认为,这些论点很大程度上定义了一个阶级的功能。假设该类是否要建立redis连接。我可能想要使用diff redis hosts作为参数创建2个单例对象,但底层的类/代码可能很常见。

1 个答案:

答案 0 :(得分:0)

正如我和评论中已经提到的那样,在依赖不可缓存的值进行缓存或记忆时,存在一些可能性。因此,如果您仍想要这样做,则以下示例不会隐藏__new____init__方法中的memoization。 (自我记忆类会有危险,因为记忆标准可能被你无法控制的代码所欺骗。)

相反,我提供了函数memoize,它返回一个类的memoizing工厂函数。由于没有通用的方法来告诉非可扩展的参数,如果它们将导致一个等效于已存在的isntance的实例,则必须明确提供memoization语义。这是通过将keyfunc函数传递给memoize来实现的。 keyfunc使用与类“__init__方法相同的参数,并返回一个哈希键,其相等关系(__eq__)决定了memoization。

正确使用memoization是使用代码的责任(提供合理的keyfunc并使用工厂),因为要记忆的类不会被修改,仍然可以正常实例化。

def memoize(cls, keyfunc):
    memoized_instances = {}

    def factory(*args, **kwargs):
        key = keyfunc(*args, **kwargs)
        if key in memoized_instances:
            return memoized_instances[key]

        instance = cls(*args, **kwargs)
        memoized_instances[key] = instance
        return instance

    return factory


class MemoTest1(object):
    def __init__(self, value):
        self.value = value

factory1 = memoize(MemoTest1, lambda value : value)

class MemoTest2(MemoTest1):
    def __init__(self, value, foo):
        MemoTest1.__init__(self, value)
        self.foo = foo

factory2 = memoize(MemoTest2, lambda value, foo : (value, frozenset(foo)))

m11 = factory1('test')
m12 = factory1('test')
assert m11 is m12

m21 = factory2('test', [1, 2])

lst = [1, 2]
m22 = factory2('test', lst)

lst.append(3)
m23 = factory2('test', lst)

assert m21 is m22
assert m21 is not m23  

我只将MemoTest2作为MemoTest1的子类包含在内,以表明使用常规类继承没有任何魔力。