이 질문은 싱글 톤 디자인 패턴 이 바람직한 지 아닌지 , 반 패턴 또는 종교적 전쟁에 대한 토론이 아니라 파이썬 에서이 패턴이 가장 파이썬적인 방식으로 가장 잘 구현되는 방법에 대해 논의하는 것입니다. 이 예에서 나는 '가장 pythonic'을 '최소한 놀랍게도의 원리'를 따른다는 것을 의미합니다 .
싱글 톤이 될 여러 클래스가 있습니다 (사용 사례는 로거를위한 것이지만 이것은 중요하지 않습니다). 나는 단순히 상속하거나 장식 할 수있을 때 잇몸이 추가 된 여러 클래스를 어지럽히고 싶지 않습니다.
최선의 방법 :
방법 1 : 데코레이터
def singleton(class_):
instances = {}
def getinstance(*args, **kwargs):
if class_ not in instances:
instances[class_] = class_(*args, **kwargs)
return instances[class_]
return getinstance
@singleton
class MyClass(BaseClass):
pass
찬성
- 데코레이터는 종종 다중 상속보다 직관적 인 방식으로 추가됩니다.
단점
- MyClass ()를 사용하여 생성 된 객체는 진정한 싱글 톤 객체이지만 MyClass 자체는 클래스가 아니라 함수이므로 클래스 메서드를 호출 할 수 없습니다. 또한
m = MyClass(); n = MyClass(); o = type(n)();
그때m == n && m != o && n != o
방법 2 : 기본 클래스
class Singleton(object):
_instance = None
def __new__(class_, *args, **kwargs):
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_, *args, **kwargs)
return class_._instance
class MyClass(Singleton, BaseClass):
pass
찬성
- 진정한 클래스입니다
단점
- 다중 상속-eugh!
__new__
두 번째 기본 클래스에서 상속하는 동안 덮어 쓸 수 있습니까? 필요 이상으로 생각해야합니다.
방법 3 : 메타 클래스
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
#Python2
class MyClass(BaseClass):
__metaclass__ = Singleton
#Python3
class MyClass(BaseClass, metaclass=Singleton):
pass
찬성
- 진정한 클래스입니다
- 상속을 자동으로 다루기
- 용도
__metaclass__
적절한 목적을 위해 (그리고 그것의 나를 인식하게)
단점
- 거기 아무도 없나요?
방법 4 : 이름이 같은 클래스를 반환하는 데코레이터
def singleton(class_):
class class_w(class_):
_instance = None
def __new__(class_, *args, **kwargs):
if class_w._instance is None:
class_w._instance = super(class_w,
class_).__new__(class_,
*args,
**kwargs)
class_w._instance._sealed = False
return class_w._instance
def __init__(self, *args, **kwargs):
if self._sealed:
return
super(class_w, self).__init__(*args, **kwargs)
self._sealed = True
class_w.__name__ = class_.__name__
return class_w
@singleton
class MyClass(BaseClass):
pass
찬성
- 진정한 클래스입니다
- 상속을 자동으로 다루기
단점
- 각각의 새 클래스를 만드는 데 오버 헤드가 없습니까? 여기서 우리는 싱글 톤으로 만들 각 클래스에 대해 두 개의 클래스를 만듭니다. 내 경우에는 괜찮지 만 이것이 확장되지 않을까 걱정됩니다. 물론이 패턴을 확장하기가 너무 쉬운 지에 대해서는 논쟁의 여지가 있습니다 ...
_sealed
속성 의 요점은 무엇입니까- 기본 클래스에서 동일한 이름의 메소드를 호출 할 수 없습니다
super()
. 즉__new__
, 호출해야하는 클래스를 사용자 정의 할 수없고 서브 클래스 할 수 없습니다__init__
.
방법 5 : 모듈
모듈 파일 singleton.py
찬성
- 단순한 것이 복잡한 것보다 낫다
단점
foo.x
또는Foo.x
대신 주장 하는 경우Foo().x
). 클래스 속성과 정적 / 클래스 메소드 (Foo.x
)를 사용하십시오.