2008-10-15 8 views
23

정기적으로 개체에 멤버가 있는지 여부를 확인하고 싶습니다. 한 가지 예는 함수에서 싱글 톤을 만드는 것입니다. 이를 위해이 같은 hasattr 사용할 수 있습니다Python의 멤버 존재 여부 확인

class Foo(object): 
    @classmethod 
    def singleton(self): 
     if not hasattr(self, 'instance'): 
      self.instance = Foo() 
     return self.instance 

을하지만 당신도 할 수있는이 :

class Foo(object): 
    @classmethod 
    def singleton(self): 
     try: 
      return self.instance 
     except AttributeError: 
      self.instance = Foo() 
      return self.instance 

다른 한 방법 더 나은가요?

편집 : 추가 @classmethod ...하지만 문제는 싱글을하지만 어떻게 객체의 멤버의 존재를 확인하는 방법에 대한 하지입니다 있습니다.

편집 : 그 예를 들어는 일반적인 사용은 다음과 같습니다

s = Foo.singleton() 

그런 다음 s 유형 Foo의 객체, 같은 각각의 시간입니다. 그리고 일반적으로이 메서드는 여러 번 호출됩니다.

+0

당신이하려는 전화의 예와 그 전화의 기대 수익을 줄 수 있습니까? – Baltimark

답변

21

: 그 코드의 주석 사본 ("스팸"그냥 무작위 클래스 인터페이스를 가지고 방법입니다) №1 LBYL (당신이 도약하기 전에 모양)이며 №2 EAFP이다 (쉽게 허락보다 용서를 구하는 것).

Pythonistas는 일반적으로 "프로세스가 테스트 할 시간과 직접 만들 때 사이에 파일을 만드는 경우 어떻게 할 것인가?"와 같은 인수를 사용하여 EAFP가 더 좋습니다. 이 주장은 여기에 적용되지 않지만 일반적인 생각입니다. 예외는 예외로 취급해서는 안됩니다.

예외적 인 관리자 설정 (try 키워드)은 CPython에서 매우 저렴합니다 (raise 키워드 및 내부 예외 생성).이 방법은 상대적으로 비용이 많이 드는 방법 인 №2를 사용합니다. 예외는 한 번만 발생합니다. 그 후에, 당신은 방금 속성을 사용합니다.

5

예외는 모델링이 잘되어야하기 때문에 어떤 경우가 "전형적"인가에 따라 다릅니다. 따라서 일반적인 경우에 instance 속성이 있어야하는 경우 두 번째 코드 스타일을 사용하십시오. instance을 가지지 않는 것이 일반적인 경우는 instance 인 경우 첫 번째 스타일을 사용하십시오.

싱글 톤을 만드는 특별한 경우에는 초기 스타일을 싱글 톤으로 만드는 것이 일반적인 사용 사례이기 때문에 첫 번째 스타일로 이동하는 경향이 있습니다. :-)

10

난 그냥 시간을 측정하려고 : 내 컴퓨터에

class Foo(object): 
    @classmethod 
    def singleton(self): 
     if not hasattr(self, 'instance'): 
      self.instance = Foo() 
     return self.instance 



class Bar(object): 
    @classmethod 
    def singleton(self): 
     try: 
      return self.instance 
     except AttributeError: 
      self.instance = Bar() 
      return self.instance 



from time import time 

n = 1000000 
foo = [Foo() for i in xrange(0,n)] 
bar = [Bar() for i in xrange(0,n)] 

print "Objs created." 
print 


for times in xrange(1,4): 
    t = time() 
    for d in foo: d.singleton() 
    print "#%d Foo pass in %f" % (times, time()-t) 

    t = time() 
    for d in bar: d.singleton() 
    print "#%d Bar pass in %f" % (times, time()-t) 

    print 

:

Objs created. 

#1 Foo pass in 1.719000 
#1 Bar pass in 1.140000 

#2 Foo pass in 1.750000 
#2 Bar pass in 1.187000 

#3 Foo pass in 1.797000 
#3 Bar pass in 1.203000 

빠른 제외하고/그 시도 할 것으로 보인다. 나에게도 더 읽기 쉽습니다. 어쨌든이 경우에 따라 달라 지므로이 테스트는 매우 간단했을 것입니다.

+0

hasattr이 백그라운드에서 예외를 사용하여 attr이 있는지 판별하기 때문에 이러한 속도 결과가 약간 오도 된 것일까? (그러나 여전히 흥미 롭다!) – seans

0

나는 Chris와 동의해야합니다. 실제로 그렇게해야 할 때까지는 최적화하지 마십시오. 나는 실존을 검사하는 것이 합당한 프로그램에서 병목 현상이 될지 의심 스럽다.

나는 이것을하기 위해 http://code.activestate.com/recipes/52558/을 보았습니다. 이 두 개의 서로 다른 방법론이다

class Singleton: 
    class __impl: 
     def spam(self): 
      return id(self) 
    __instance = None 
    def __init__(self): 
     if Singleton.__instance is None: 
      Singleton.__instance = Singleton.__impl() 
     self.__dict__['_Singleton__instance'] = Singleton.__instance 
    def __getattr__(self, attr): 
     return getattr(self.__instance, attr) 
    def __setattr__(self, attr, value): 
     return setattr(self.__instance, attr, value) 
+0

그리고'self .__ dict __ [ '_ Singleton__instance'] = Singleton .__ 인스턴스'? 이것은 self와 동일해야합니다 .__ instance = Singleton .__ 인스턴스, 그렇지 않습니까? – PierreBdR

1

사용 방법에 약간의 논픽션. 싱글 톤은 과대 평가하고, "공유 상태"방법은 예를 들어, 효과, 그리고 파이썬에서 대부분 매우 깨끗 : 이제

class Borg: 
    __shared_state = {} 
    def __init__(self): 
     self.__dict__ = self.__shared_state 
    # and whatever else you want in your class -- that's all! 

때마다 당신이 할 :

obj = Borg() 

가있을 것이다 동일한 정보, 또는 다소 동일한 경우.

관련 문제