[英]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.