__slots__使ってみた

Pythonのクラス定義で__slots__でクラスの属性を指定するとクラスをインスタンス化するとき__dict__を作成しないため

  • メモリを節約
  • 参照、代入可能な属性を固定

できるらしい。。。

実際のところどの程度メモリを節約できるのかに興味をもったので、100万のオブジェクトを作ってメモリ使用量をテキトーに測ってみた。

環境はInspiron mini9のwindowsモデルで、メモリ使用量はWindowsタスクマネージャで適当に測りました(お

#! /usr/local/bin/python2.6
# coding: utf-8
# slots.py
# 省メモリと属性の凍結の機能を持つ__slots__のテスト

class Empty(object):
    pass
class EmptySlots(object):
    __slots__ = []

# [Class]     [MB]
# Empty         40
# EmptySlots    16
def main():
    import sys
    klass = None
    if sys.argv[1] == "slots":
        klass = EmptySlots
    else:
        klass = Empty
    print klass
    lst = []
    for i in xrange(1000000):
        p = klass()
        lst.append(p)
    raw_input(">")

if __name__ == '__main__':
    main()

結果は__slots__を使用する場合16MB、しない場合は40MBでした。

次に、2つの属性x,yを持つクラスを定義して同様にメモリ使用量を測りました。

#! /usr/local/bin/python2.6
# coding: utf-8
# slots2.py
# 省メモリと属性の凍結の機能を持つ__slots__のテスト

class Point(object):
    def __init__(self):
        self.x = 0.0
        self.y = 0.0

class PointSlots(object):
    __slots__ = ["x", "y"]

# [Class]     [MB]
# Point        186
# PointSlots    40
def main():
    import sys
    klass = None
    if sys.argv[1] == "slots":
        klass = PointSlots
    else:
        klass = Point
    print klass
    lst = []
    for i in xrange(1000000):
        p = klass()
        p.x = p.y = 0.0
        lst.append(p)
    raw_input(">")

if __name__ == '__main__':
    main()

結果は__slots__使用で40MB、しない場合で184MBで差は146MBでした。