使isinstance(obj,cls)与装饰类一起工作

Ara*_*Fey 4 python class python-2.7 python-decorators

我有几个类需要执行以下操作:

调用构造函数时,如果已存在相等的对象(也称为具有相同id的对象),则返回该对象.否则,创建一个新实例.基本上,

>>> cls(id=1) is cls(id=1)
True
Run Code Online (Sandbox Code Playgroud)

为此,我编写了一个类装饰器,如下所示:

class Singleton(object):
    def __init__(self, cls):
        self.__dict__.update({'instances': {},
                                'cls': cls})

    def __call__(self, id, *args, **kwargs):
        try:
            return self.instances[id]
        except KeyError:
            instance= self.cls(id, *args, **kwargs)
            self.instances[id]= instance
            return instance

    def __getattr__(self, attr):
        return getattr(self.cls, attr)
    def __setattr__(self, attr, value):
        setattr(self.cls, attr, value)
Run Code Online (Sandbox Code Playgroud)

这样做我想要的,但是:

@Singleton
class c(object):
    def __init__(self, id):
        self.id= id

o= c(1)
isinstance(o, c) # returns False
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个问题?我发现了一个相关的问题,但我似乎无法将这些解决方案改编为我的用例.


我知道有人要我发布一些不起作用的代码,所以你去了:

def Singleton(cls):
    instances= {}
    class single(cls):
        def __new__(self, id, *args, **kwargs):
            try:
                return instances[id]
            except KeyError:
                instance= cls(id, *args, **kwargs)
                instances[id]= instance
                return instance
    return single
# problem: isinstance(c(1), c) -> False

def Singleton(cls):
    instances= {}
    def call(id, *args, **kwargs):
        try:
            return instances[id]
        except KeyError:
            instance= cls(id, *args, **kwargs)
            instances[id]= instance
            return instance
    return call
# problem: isinstance(c(1), c) -> TypeError
Run Code Online (Sandbox Code Playgroud)

Ash*_*ary 5

您可以__instancecheck__在装饰器类中添加自定义挂钩:

def __instancecheck__(self, other):
    return isinstance(other, self.cls)
Run Code Online (Sandbox Code Playgroud)