>  기사  >  백엔드 개발  >  Python에서 싱글톤 패턴을 만드는 5가지 일반적인 방법

Python에서 싱글톤 패턴을 만드는 5가지 일반적인 방법

高洛峰
高洛峰원래의
2016-10-18 09:31:521032검색

소위 싱글톤이란 클래스의 인스턴스가 처음부터 끝까지 한 번만 생성될 수 있음을 의미합니다.

방법 1

클래스의 인스턴스가 처음부터 끝까지 하나만 있도록 하려면 __new__ 메서드를 사용하면 매우 간단합니다. Python의 클래스는 __new__를 통해 인스턴스를 생성합니다.

class Singleton(object):
    def __new__(cls,*args,**kwargs):
        if not hasattr(cls,'_inst'):
            cls._inst=super(Singleton,cls).__new__(cls,*args,**kwargs)
        return cls._inst
if __name__=='__main__':
    class A(Singleton):
        def __init__(self,s):
            self.s=s      
    a=A('apple')   
    b=A('banana')
    print id(a),a.s
    print id(b),b.s


결과:

29922256 바나나

29922256 바나나

클래스 인스턴스가 생성될 때 클래스 속성 _inst에 바인딩하려면 __new__ 메서드를 사용하세요. cls._inst가 None이면 클래스가 인스턴스화되지 않았음을 의미합니다. 인스턴스를 인스턴스화하고 cls._inst에 바인딩합니다. 첫 번째 인스턴스화로 생성된 인스턴스는 나중에 인스턴스화될 때마다 반환됩니다. Singleton에서 하위 클래스를 파생할 때 __new__를 오버로드하지 마세요.

방법 2:

생성된 인스턴스가 동일한 ID를 가지고 있는지 여부는 신경 쓰지 않고 상태와 동작에만 관심이 있는 경우가 있습니다. 많은 인스턴스가 생성되도록 허용할 수 있지만 모든

class Borg(object):
    _shared_state={}
    def __new__(cls,*args,**kwargs):
        obj=super(Borg,cls).__new__(cls,*args,**kwargs)
        obj.__dict__=cls._shared_state
        return obj

은 모든 인스턴스의 __dict__가 동일한 사전을 가리키므로 인스턴스가 동일하게 공유합니다. 메소드와 속성. __init__에서 수정했든 직접 수정했든 모든 인스턴스의 name 속성 설정은 모든 인스턴스에 영향을 미칩니다. 그러나 인스턴스 ID는 다릅니다. 클래스 인스턴스가 속성을 공유할 수 있지만 하위 클래스와는 공유할 수 없도록 하려면 Borg._shared_state 대신 cls._shared_state를 사용해야 합니다.

인스턴스마다 ID가 다르기 때문에 각 인스턴스를 사전 키로 사용할 수 있습니다.

if __name__=='__main__':
    class Example(Borg):
        pass
    a=Example()
    b=Example()
    c=Example()
    adict={}
    j=0
    for i in a,b,c:
        adict[i]=j
        j+=1
    for i in a,b,c:
        print adict[i]

결과:

0

1

2

이 동작이 원하는 것이 아니라면 Borg 클래스에 __eq__ 및 __hash__ 메서드를 추가하여 싱글톤에 가까운 동작으로 만들 수 있습니다. 패턴:

class Borg(object):
    _shared_state={}
    def __new__(cls,*args,**kwargs):
        obj=super(Borg,cls).__new__(cls,*args,**kwargs)
        obj.__dict__=cls._shared_state
        return obj
    def __hash__(self):
        return 1
    def __eq__(self,other):
        try:
            return self.__dict__ is other.__dict__
        except:
            return False
if __name__=='__main__':
    class Example(Borg):
        pass
    a=Example()
    b=Example()
    c=Example()
    adict={}
    j=0
    for i in a,b,c:
        adict[i]=j
        j+=1
    for i in a,b,c:
        print adict[i]

결과:

2

2

2

모든 인스턴스를 키로 사용할 수 있습니다.

방법 3

클래스를 작성할 때 일부 메커니즘은 클래스 이름, 기본 클래스 튜플 및 클래스 사전을 사용하여 클래스 객체를 생성합니다. 새 클래스의 이 메커니즘은 기본적으로 유형이며 이 메커니즘은 프로그래밍 가능하며 메타클래스 __metaclass__라고 합니다.

class Singleton(type):
    def __init__(self,name,bases,class_dict):
        super(Singleton,self).__init__(name,bases,class_dict)
        self._instance=None
    def __call__(self,*args,**kwargs):
        if self._instance is None:
            self._instance=super(Singleton,self).__call__(*args,**kwargs)
        return self._instance
if __name__=='__main__':
    class A(object):
        __metaclass__=Singleton       
    a=A()
    b=A()
    print id(a),id(b)

결과:

34248016

id가 동일합니다.

이 예에서는 Singleton 메타클래스를 생성하고 __call__ 메서드를 사용하여 함수 동작을 시뮬레이션합니다. 클래스 A를 생성할 때 해당 메타클래스를 싱글톤으로 설정한 다음 클래스 객체 A를 생성할 때 동작은 다음과 같습니다.

A=Singleton(name, bases, class_dict), A는 실제로 싱글톤 클래스의 인스턴스입니다. .

A의 인스턴스를 생성할 때 A()=Singleton(name,bases,class_dict)()=Singleton(name,bases,class_dict).__call__(), 따라서 A의 모든 인스턴스를 가리킵니다. A의 _instance 속성, 이 메소드는 실제로 메소드 1과 동일합니다.

방법 4

파이썬의 모듈 모듈은 프로그램에서 한 번만 로드되며 싱글톤 그 자체입니다. 모듈을 직접 작성하고 모듈에 필요한 메소드와 속성을 모듈 범위의 함수 및 전역 변수로 작성할 수 있습니다. 클래스를 작성할 필요가 전혀 없습니다.

그리고 모듈과 클래스의 장점을 결합하는 몇 가지 방법이 있습니다.

class _singleton(object):
    class ConstError(TypeError):
        pass
    def __setattr__(self,name,value):
        if name in self.__dict__:
            raise self.ConstError
        self.__dict__[name]=value
    def __delattr__(self,name):
        if name in self.__dict__:
            raise self.ConstError
        raise NameError
import sys
sys.modules[__name__]=_singleton()

Python은 sys.modules를 확인하지 않습니다. 모듈 개체이므로 이를 사용하여 모듈을 클래스 개체에 바인딩하고 나중에 동일한 개체에 바인딩할 것입니다.

Single.py에 코드를 저장합니다:

>>> import single
>>> single.a=1
>>> single.a=2

ConstError

>>> del Single.a

ConstError

방법 5

가장 간단한 방법:


class singleton(object):
    pass
singleton=singleton()

싱글톤이라는 이름을 인스턴스에 바인딩합니다. 싱글톤은 해당 클래스의 유일한 개체입니다.


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.