本文介绍了Python:基于参数的单例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注此,并尝试进行单身人士课程。但是,考虑参数(在启动类时传递),以便如果参数相同,则返回相同的对象。

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:基于参数的单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 07:10