所以我正在创建一个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__
?
答案 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()