2014-11-14 3 views
1

싱글 톤을 만드는 방법을 배우고 있습니다. (제발, 여기서 싱글 톤이 좋지 않다고 생각하지 마십시오. 하나의 구현을 바탕으로 "장식 자 클래스"가 Python에서 작동하는 방법에 대한 설명이 필요합니다.

, 나는 다음과 같이 그 일을 시도 :

class Singleton(object): 
    def __init__(self, klass): 
     print "S init" 
     self.klass = klass 
     self.instance = None 
    def __call__(self, *args, **kwargs): 
     print "S call" 
     if self.instance is None: 
      self.instance = self.klass(*args, **kwargs) 
     else: 
      self.instance(*args, **kwargs) 
     return self.instance 

@Singleton 
class KlasseA: 
    def __new__(cls, *args, **kwargs): 
     print "KA new" 
    def __init__(self, s): 
     print "KA init" 
     self.__init2(s) 
    def __call__(self, s=None): 
     print "KA call" 
     self.__init2(s) 
    def __init2(self, s): 
     if s: self.s = s 

@Singleton 
class KlasseB: 
    def __new__(cls, *args, **kwargs): 
     print "KB new" 
    def __init__(self, s): 
     print "KB init" 
     self.__init2(s) 
    def __call__(self, s=None): 
     print "KB call" 
     self.__init2(s) 
    def __init2(self, s): 
     if s: self.s = s 

를 이제 같은 평 파일에 다음 줄을 추가하여 위의 테스트 :

print "" 
a = KlasseA('one') 
print "a -> ", id(a), a.s 
b = KlasseA('two') 
print "b -> ", id(b), b.s 
print "a -> ", id(a), a.s 
c = KlasseA() 
print "c -> ", id(c), c.s 
print "b -> ", id(b), b.s 
print "a -> ", id(a), a.s 
d = KlasseB('three') 
print "d -> ", id(d), d.s 
print "a -> ", id(a), a.s 

내가있어 다음 :

S init 
S init 

S call 
KA init 
a -> 140525844905496 one 
S call 
KA call 
b -> 140525844905496 two 
a -> 140525844905496 two 
S call 
KA call 
c -> 140525844905496 two 
b -> 140525844905496 two 
a -> 140525844905496 two 
S call 
KB init 
d -> 140525844905568 three 
a -> 140525844905496 two 

따라서 싱글 톤 데코레이터가 실제로 작동합니다. 내가 여기에 이해가 안 무엇 :

  1. 나는 전화를 재정의 장식 생각, 그래서 전화 KlasseA() 효과적으로 Singleton(KlasseA)()를 호출합니다. 이로 인해 KlasseA() 호출마다 새로운 Singleton 인스턴스가 생성되지 않아야합니까?

  2. KlasseAKlasseB의 선언 중에 Singleton()이 호출 되었기 때문에 "S init"라인이 두 개인 것으로 나타났습니다. 따라서 Singleton의 두 인스턴스가 생성되었습니다. 이 인스턴스들은 어디에 보관 되었습니까?

  3. 위의 싱글 톤 데코레이터 레시피에는 '잡았다'가있을 수 있습니까?

답변

1

데코레이터는 클래스가 정의 될 때 적용되며 인스턴스화 될 때 적용되지 않습니다. 위의 그림과 같이 점 2에 관한

class KlasseA(): 
    ... 

KlasseA = Singleton(KlasseA) 

a = KlasseA() 

, 이름 KlasseAKlasseBSingleton의 인스턴스에 바인딩됩니다 : 당신의 점 1에 관해서는, 그것은 정말 상당합니다.

포인트 3과 관련하여, 새 인스턴스를 만들려고했기 때문에 클래스의 단일 인스턴스에 대해 __call__ 메서드를 호출하는 것이 합리적이지는 않습니다. 즉, 나는 Singleton.__call__을 간단히 말해야한다고 생각한다.

def __call__(self, *args, **kwargs): 
    if self.instance is None: 
     self.instance = self.klass(*arg, **kwargs) 
    return self.instance 
+0

아아아, 알 겠어! 그래서 (개념적으로) 클래스 자체의 정의를 재정의하고,'Singleton' 클래스의 인스턴스는'KlasseA'와'KlasseB'의 클래스 정의에 바인딩됩니다. – pepoluan

+0

# 3의 경우, __call__을 래핑 된 클래스의''__call__' 메서드에 전달하면 안됩니까? 'else :'절을 삭제하면'b = KlasseA ('two')'는 더 이상'b.s' 속성에 영향을 미치지 않습니다. – pepoluan

+0

글쎄, 수업을 어떻게 할 것인가에 달려 있습니다. 개념적으로,'Singleton .__ call__'은'a = KlasseA()'를 쓸 때 실제로'type .__ call__'의 롤을 채 웁니다; 그것은 함수처럼 클래스 이름이 사용되는 것을 의미하는 것을 결정하는 함수입니다. 반면에'KlasseA .__ call__'은'KlasseA'의 * 인스턴스 *가 함수처럼 사용되는 것을 결정하는 데 사용됩니다 :'a()'. – chepner

관련 문제