2017-12-13 19 views
0

그래서 저는 메모 된 수업을 만들고 이상한 행동을 관찰하고 있습니다.Memoized 객체는 여전히 __init __()가 호출 되었습니까?

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

'__new__'을 정의하면 일반적으로'__new__'에서 모든 초기화 작업을 수행합니다. '__init__'를 전혀 정의하지 마십시오. – ShadowRanger

답변

1

__new__의 목적은 새 인스턴스를 만드는 것입니다. 따라서이 인스턴스에서 파이썬은 __init__을 호출합니다. 새 인스턴스를 만들지 않으려면 metaclass에서 __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() 
+0

음,'__new__'에 대한 호출을 가로 채기 만하면 실제로 새로운 인스턴스를 만들 수 없습니다. 'id (w1)'과'id (wx)'에 대해 동일한 값을 주목하라. 그러나 메타 클래스를 사용하면 흥미롭고 가치있는 공부를 할 수 있습니다. 조언 주셔서 감사합니다! – pepoluan

+0

Whoops는 코드를 그대로 사용하고 2 개의 다른 인스턴스 인 SomeClass로 끝났습니다. 마지막 줄은 다음과 같습니다 :'10739744 140559844255336 False' – pepoluan

+1

돌아오다 돌아 가기 –