싱글톤
1.인스턴시에이터(Instantiator)
class Test:
def __new__(cls, *args, **kwargs):
print("im new")
# 현재 자신인 Test를 가르킨다.
print(cls)
print(args)
print(kwargs)
# Object의 객체를 생성하고 반환(메모리에 할당하는 부분)
obj = super().__new__(cls)
#현재 cls인 Test를 받았기에 출력은 Test클래스로 나오지만 실제로는 Object의 객체이다.
print("created obj", obj)
return obj
def __init__(self, x, y):
# 다양한 매개변수들을 받고 인스턴스 속성들을 설정한다.
print("im init")
self.x = x
self.y = y
test1 = Test(10, 20)
im new
<class '__main__.Test'>
(10, 20)
{}
created obj <__main__.Test object at 0x100977bb0>
im init
2.생성자(Constructor)
class Test1:
def __init__(self, name):
self.name = name
class Test2(Test1):
def __init__(self, name, age):
# 자신의 부모 클래스인 Test1을 가르킨다.
super().__init__(name)
self.age = age
test = Test2("steve", 20)
print(test)
print(test.name)
print(test.age)
<__main__.Test2 object at 0x103177b80>
steve
20
싱글톤생성 방법
싱글톤은 메모리상에 객체가 한번만 할당되는 것이 중요하기에 new 메서드를 잘 이용해야한다.
class SingleTon:
def __new__(cls):
# 아직 생성된 인스턴스가 없다면 새롭게 인스턴스를 생성
if not hasattr(cls, "instance"):
print("create single instance!")
cls.instance = super().__new__(cls)
else:
print("use maden single instance!")
return cls.instance
def __init__(self):
print("init!")
for i in range(10):
instance = SingleTon()
print(i, "번째 인스턴스:", instance)
create single instance!
init!
0 번째 인스턴스: <__main__.SingleTon object at 0x102967b50>
use maden single instance!
init!
1 번째 인스턴스: <__main__.SingleTon object at 0x102967b50>
use maden single instance!
init!
2 번째 인스턴스: <__main__.SingleTon object at 0x102967b50>
use maden single instance!
init!
3 번째 인스턴스: <__main__.SingleTon object at 0x102967b50>
use maden single instance!
init!
4 번째 인스턴스: <__main__.SingleTon object at 0x102967b50>
use maden single instance!
init!
5 번째 인스턴스: <__main__.SingleTon object at 0x102967b50>
use maden single instance!
init!
6 번째 인스턴스: <__main__.SingleTon object at 0x102967b50>
use maden single instance!
init!
7 번째 인스턴스: <__main__.SingleTon object at 0x102967b50>
use maden single instance!
init!
8 번째 인스턴스: <__main__.SingleTon object at 0x102967b50>
use maden single instance!
init!
9 번째 인스턴스: <__main__.SingleTon object at 0x102967b50>
class SingleTon:
__instance = None
#외부에서 접근 불가능한 메서드
@classmethod
def __getInstance(cls):
return cls.__instance
@classmethod
def instance(cls, *args, **kargs):
# 인스턴스 한 개를 할당
cls.__instance = cls(*args, **kargs)
# 인스턴스 한 개를 할당하는 메서드인 instance를 가져오는 메서드인 __getInstance로 대치(초기에 한번 불려오면 현재의 기능은 없어지기 때문에 메모리에 한번만 적재할 수 있다.)
cls.instance = cls.__getInstance
# 생성된 인스턴스 반환
return cls.__instance
for i in range(10):
instance = SingleTon.instance()
print(i, "번째 인스턴스:", instance)
0 번째 인스턴스: <__main__.SingleTon object at 0x100fa3af0>
1 번째 인스턴스: <__main__.SingleTon object at 0x100fa3af0>
2 번째 인스턴스: <__main__.SingleTon object at 0x100fa3af0>
3 번째 인스턴스: <__main__.SingleTon object at 0x100fa3af0>
4 번째 인스턴스: <__main__.SingleTon object at 0x100fa3af0>
5 번째 인스턴스: <__main__.SingleTon object at 0x100fa3af0>
6 번째 인스턴스: <__main__.SingleTon object at 0x100fa3af0>
7 번째 인스턴스: <__main__.SingleTon object at 0x100fa3af0>
8 번째 인스턴스: <__main__.SingleTon object at 0x100fa3af0>
성능비교
from memory_profiler import profile
import time
class SingleTon1:
def __new__(cls):
# 아직 생성된 인스턴스가 없다면 새롭게 인스턴스를 생성
if not hasattr(cls, "instance"):
cls.instance = super().__new__(cls)
return cls.instance
class SingleTon2:
__instance = None
# 외부에서 접근 불가능한 메서드
@classmethod
def __getInstance(cls):
return cls.__instance
@classmethod
def instance(cls, *args, **kargs):
# 인스턴스 한 개를 할당
cls.__instance = cls(*args, **kargs)
# 인스턴스 한 개를 할당하는 메서드인 instance를 가져오는 메서드인 __getInstance로 대치(초기에 한번 불려오면 현재의 기능은 없어지기 때문에 메모리에 한번만 적재할 수 있다.)
cls.instance = cls.__getInstance
# 생성된 인스턴스 반환
return cls.__instance
loop = 1000000
@profile
def useNew():
for i in range(loop):
instance = SingleTon1()
@profile
def useClassMethod():
for i in range(loop):
instance = SingleTon2.instance()
def execute_time_new():
for i in range(loop):
instance = SingleTon1()
def execute_class_method():
for i in range(loop):
instance = SingleTon2.instance()
print("===================Memory compare===================")
print("-------------------with new")
useNew()
print("-------------------with ClassMethod")
useClassMethod()
print("===================Execute Time compare===================")
print("-------------------with new")
start = time.time()
execute_time_new()
print("time :", time.time() - start)
print("-------------------with ClassMethod")
start = time.time()
execute_class_method()
print("time :", time.time() - start)
===================Memory compare===================
-------------------with new
Filename:
경로생략
Line # Mem usage Increment Occurrences Line Contents
=============================================================
62 20.3 MiB 20.3 MiB 1 @profile
63 def useNew():
64 20.4 MiB 0.1 MiB 1000001 for i in range(loop):
65 20.4 MiB 0.1 MiB 1000000 instance = SingleTon1()
-------------------with ClassMethod
Filename:
경로생략
Line # Mem usage Increment Occurrences Line Contents
=============================================================
68 20.5 MiB 20.5 MiB 1 @profile
69 def useClassMethod():
70 20.5 MiB 0.0 MiB 1000001 for i in range(loop):
71 20.5 MiB 0.0 MiB 1000000 instance = SingleTon2.instance()
===================Execute Time compare===================
-------------------with new
time : 0.09079909324645996
-------------------with ClassMethod
time : 0.07572388648986816