已记忆的对象仍会调用其 __init__() 吗?

Memoized objects still have their __init__() invoked?

所以我正在创建一个记忆 class,并且一直在观察一个奇怪的行为。

这是代码片段:

class SomeClass(object):

    _Memoized = {}

    def __new__(cls, id: str, *args, **kwargs):
        if id not in cls._Memoized:
            print('New Instance')
            cls._Memoized[id] = super(SomeClass, cls).__new__(cls, *args, **kwargs)
        else:
            print('Existing Instance')
        return cls._Memoized[id]

    def __init__(self, id: str):
        print('Running init')
        self.id = id


def test():
    w1 = SomeClass(id='w1')
    wx = SomeClass(id='w1')
    print(id(w1), id(wx), id(w1) == id(wx))

test()

运行 上面的代码导致:

New Instance
Running init
Existing Instance
Running init   <===-------------------???
140008534476784 140008534476784 True

我的问题:在第二次调用SomeClass()时,为什么执行__init__构造函数? __init__ 构造函数不是只在实例化时调用吗?有没有办法阻止 __init__ 被调用?

__new__ 的目的是创建一个新实例,这就是 Python 在其上调用 __init__ 的原因。您可以改写元类上的 __call__ 以避免创建新实例。

class MemoMeta(type):
    def __init__(self, name, bases, namespace):
        super().__init__(name, bases, namespace)
        self.cache = {}
    def __call__(self, id_, *args, **kwargs):
        if id_ not in self.cache:
            print('New Instance')
            self.cache[id_] = super().__call__(id_, *args, **kwargs)
        else:
            print('Existing Instance')
        return self.cache[id_]

class SomeClass(metaclass=MemoMeta):
    def __init__(self, id_, *args, **kwargs):
        print('Running init')
        self.id = id_


def test():
    w1 = SomeClass(id_='w1')
    wx = SomeClass(id_='w1')
    print(id(w1), id(wx), id(w1) == id(wx))

test()