[Python] __slots__의 효과
__dict__의 단점과 해결책
파이썬은 __dict__의 이름으로 객체 하나당 하나씩 딕셔너리를 할당한다. 그런데 딕셔너리는 리스트나 튜플에 비해 메모리 사용량이 많다. ‘키’를 이용해 ‘값’을 바로 얻을 수 있도록 하기 위해서 파이썬이 더 많은 정보를 유지하기 때문이다.
이러한 부담을 줄이기 위해 __slots__라는 것을 사용한다.
class Point3D:
def __init__(self, x, y, z):
self.x = x # x 좌표
self.y = y # y 좌표
self.z = z # z 좌표
def __str__(self):
return '({0}, {1}, {2})'.format(self.x, self.y, self.z)
class Point3D:
__slots__ = ('x', 'y', 'z')
def __init__(self, x, y, z):
self.x = x # x 좌표
self.y = y # y 좌표
self.z = z # z 좌표
def __str__(self):
return '({0}, {1}, {2})'.format(self.x, self.y, self.z)
def main():
p1 = Point3D(1, 1, 1) # 3차원 좌표상의 한 점
p2 = Point3D(24, 17, 31) # 3차원 좌표상의 한 점
print(p1)
print(p2)
(1,1,1)
(24,17,31)
위 코드를 보면 __slots__를 이용하는 형태로 수정한 코드가 추가되있다.
__slots__ = (‘x’, ‘y’, ‘z’) 의 의미는 이 클래스를 기반으로 생성한 객체의 변수는 x,y,z로 제한한다는 의미이다. 이 코드를 통해 p1.w=30; 등과 같이 객체에 변수를 추가하는 것은 불가능하다.
__slots__를 통해 변수의 수와 이름을 제한하면 객체별로 __dict__이 생기지 않는다. 또 객체별로 __slots__가 하나씩 갖는 것이 아니라 클래스당 하나의 __slots__만 생성되기 때문에 메모리상 이득이 된다.
__dict__ 과 __slots__의 속도차이
__slots__가 존재하는 경우 객체 내에 있는 변수에 접근하는 데 있어 속도 상의 이점도 있다.
- __dict__
import timeit
class Point3D:
def __init__(self, x, y, z):
self.x = x # x 좌표
self.y = y # y 좌표
self.z = z # z 좌표
def __str__(self):
return '({0}, {1}, {2})'.format(self.x, self.y, self.z)
def main():
start = timeit.default_timer()
p = Point3D(1, 1, 1)
for i in range(3000):
for i in range(3000):
p.x += 1
p.y += 1
p.z += 1
print(p)
stop = timeit.default_timer()
print(stop - start)
main()
(9000001, 9000001, 9000001)
4.1482692
- __slots__
import timeit
class Point3D:
__slots__ = ('x', 'y', 'z')
def __init__(self, x, y, z):
self.x = x # x 좌표
self.y = y # y 좌표
self.z = z # z 좌표
def __str__(self):
return '({0}, {1}, {2})'.format(self.x, self.y, self.z)
def main():
start = timeit.default_timer()
p = Point3D(1, 1, 1)
for i in range(3000):
for i in range(3000):
p.x += 1
p.y += 1
p.z += 1
print(p)
stop = timeit.default_timer()
print(stop - start)
main()
(9000001, 9000001, 9000001)
3.4330227
위 코드를 통해 __slots__가 있을 때 더 적은 시간이 걸렸음을 확인할 수 있다.