简体   繁体   English

Python:基于参数的单例

[英]Python : Argument based Singleton

I'm following this link and trying to make a singleton class. 我正在跟踪此链接,并尝试制作单例课程。 But, taking arguments (passed while initiating a class) into account so that the same object is returned if the arguments are same. 但是,请考虑参数(在初始化类时传递的参数),以便在参数相同的情况下返回相同的对象。

So, instead of storing class name/class reference as a dict key, I want to store passed arguments as keys in dict . 因此,我不想将传递的自变量作为键存储在dict ,而不是将类名/类引用存储为dict键。 But, there could be unhashable arguments also (like dict , set itself). 但是,也可能存在无法散列的参数(例如dict ,请自行set )。

What is the best way to store class arguments and class objects mapping? 存储类参数和类对象映射的最佳方法是什么? So that I can return an object corresponding to the arguments. 这样我就可以返回与参数相对应的对象。

Thanks anyways. 不管怎么说,多谢拉。


EDIT-1 : A little more explanation. EDIT-1 :更多解释。 Let's say there is class as follows 假设有以下课程

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

Now, A(1,2) should always return the same object. 现在, A(1,2)应该始终返回相同的对象。 But, it should be different from A(3,4) 但是,它应该不同于A(3,4)

I think, the arguments very much define the functioning of a class. 我认为,参数很大程度上定义了类的功能。 Let's say if the class is to make redis connections. 假设该类是否要建立redis连接。 I might want to create 2 singletons objects with diff redis hosts as parameters, but the underlying class/code could be common. 我可能想用diff redis主机作为参数创建2个单例对象,但是底层的类/代码可能很常见。

As theheadofabroom and me already mentioned in the comments, there are some odds when relying on non-hashable values for instance caching or memoization. 正如评论中提到的“ headofabroom”和我所说的那样,在依靠不可散列的值进行缓存或记忆化时存在一些奇怪之处。 Therefore, if you still want to do exactly that, the following example does not hide the memoization in the __new__ or __init__ method. 因此,如果您仍然想做到这一点,下面的示例不会在__new____init__方法中隐藏__new__ (A self-memoizing class would be hazardous because the memoization criterion can be fooled by code that you don't control). (自记忆类很危险,因为记忆标准可能会被您无法控制的代码所欺骗)。

Instead, I provide the function memoize which returns a memoizing factory function for a class. 取而代之的是,我提供了函数memoize ,该函数返回一个类的备忘录工厂功能。 Since there is no generic way to tell from non-hashable arguments, if they will result in an instance that is equivalent to an already existing isntance, the memoization semantics have to be provided explicitly. 由于没有通用的方法可以从非哈希参数中分辨出来,因此如果它们会导致实例等同于已经存在的等价物,则必须显式提供备注语义。 This is achieved by passing the keyfunc function to memoize . 这是通过将keyfunc函数传递给memoize keyfunc takes the same arguments as the class' __init__ method and returns a hashable key, whose equality relation ( __eq__ ) determines memoization. keyfunc采用与类的__init__方法相同的参数,并返回一个可散列的键,其相等关系( __eq__ )确定备注。

The proper use of the memoization is in the responsibility of the using code (providing a sensible keyfunc and using the factory), since the class to be memoized is not modified and can still be instantiated normally. 备注的正确使用由使用代码(提供合理的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  

I only included MemoTest2 as a sublclass of MemoTest1 to show that there is no magic involved in using regular class inheritance. 我仅将MemoTest2作为MemoTest1的MemoTest1包括在内,以表明使用常规类继承不会涉及任何魔术。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM