问题描述
我正在关注此,并尝试进行单身人士课程。但是,考虑参数(在启动类时传递),以便如果参数相同,则返回相同的对象。
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.
所以,而不是存储类名/类引用为 dict
键,我想将传递的参数存储在 dict
中的键。但是,也可能有不可争议的论据(如 dict
,设置
本身)。
So, instead of storing class name/class reference as a dict
key, I want to store passed arguments as keys in dict
. But, there could be unhashable arguments also (like dict
, set
itself).
存储类参数和类对象的最佳方法是映射?所以我可以返回一个与参数相对应的对象。
What is the best way to store class arguments and class objects mapping? So that I can return an object corresponding to the arguments.
无论如何。
EDIT-1 :
再多一点解释。假设有类如下
EDIT-1 :A little more explanation. Let's say there is class as follows
class A:
__metaclass__ == Singleton
def __init__(arg1, arg2):
pass
现在, A(1, 2)
应该始终返回相同的对象。但是,它应该不同于 A(3,4)
Now, A(1,2)
should always return the same object. But, it should be different from A(3,4)
我认为,这些论点非常定义班的功能假设课程是要使 redis
连接。我可能想要创建2个单例对象,其中diff redis
hosts作为参数,但底层类/代码可能是常见的。
I think, the arguments very much define the functioning of a class. Let's say if the class is to make redis
connections. I might want to create 2 singletons objects with diff redis
hosts as parameters, but the underlying class/code could be common.
推荐答案
由于在评论中已经提到过,所以有一些可能性,当依赖不可哈希的值,例如缓存或记忆化。因此,如果您仍然想要做到这一点,以下示例不会隐藏 __ new __
或 __ init __
中的回调方法。 (一个自我回忆的类将是危险的,因为记忆标准可以被你不能控制的代码所迷惑)。
As theheadofabroom and me already mentioned in the comments, there are some odds when relying on non-hashable values for instance caching or memoization. Therefore, if you still want to do exactly that, the following example does not hide the memoization in the __new__
or __init__
method. (A self-memoizing class would be hazardous because the memoization criterion can be fooled by code that you don't control).
而是提供函数 memoize
它返回一个类的记忆工厂函数。由于没有通用的方法可以从不可散列的参数中得出结论,如果它们将导致一个等同于已经存在的isntance的实例,则必须明确提供记忆语义。这是通过将 keyfunc
函数传递给 memoize
来实现的。 keyfunc
采用与类' __ init __
方法相同的参数,并返回一个可哈希的密钥,其等式关系( __ eq __
)确定记忆。
Instead, I provide the function memoize
which returns a memoizing factory function for a class. 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
takes the same arguments as the class' __init__
method and returns a hashable key, whose equality relation (__eq__
) determines memoization.
正确使用记忆是使用代码的责任(提供一个明智的 keyfunc
并使用工厂),因为要记录的类不会被修改,并且仍然可以正常实例。
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.
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
的子类,以显示使用常规类继承没有任何魔法。
I only included MemoTest2
as a sublclass of MemoTest1
to show that there is no magic involved in using regular class inheritance.
这篇关于Python:基于参数的单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!