记忆对象仍然调用了__init __()?

时间:2017-12-13 05:02:16

标签: python-3.x python-3.5 memoization

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

以下是代码片段:

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__

1 个答案:

答案 0 :(得分:2)

__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()