3

我正在关注这个链接并尝试制作一个单例类。但是,考虑参数(在启动类时传递),以便在参数相同时返回相同的对象。

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

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

不管怎么说,多谢拉。


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

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

现在,A(1,2)应该总是返回相同的对象。但是,它应该不同于A(3,4)

我认为,这些论点在很大程度上定义了一个类的功能。假设班级是否要redis建立联系。我可能想创建 2 个以 diffredis主机作为参数的单例对象,但底层的类/代码可能很常见。

4

1 回答 1

0

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

相反,我提供了一个函数memoize,它返回一个类的记忆工厂函数。由于没有通用的方法来区分不可散列的参数,如果它们会产生一个与已经存在的实例等效的实例,则必须显式地提供记忆语义。这是通过将keyfunc函数传递给memoize. keyfunc采用与类的方法相同的参数__init__并返回一个可散列键,其相等关系 ( __eq__) 确定记忆。

memoization 的正确使用是 using 代码的责任(提供一个keyfuncsensible 和 using 工厂),因为要 memoized 的类没有被修改,仍然可以正常实例化。

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以表明使用常规类继承没有任何魔力。

于 2016-08-19T11:33:02.973 回答