この記事では、クラスで使用するデータメンバーを「__slots__」を使って明示的に指定する方法を解説します。
クラスで使用するデータメンバーを明示的に指定することで、そのクラスを「軽量化」 + 「高速化」することができます。
それでは、指定する方法を見ていきましょう!
指定方法
クラスに__slots__という名前のクラス変数を定義します。__slots__には、そのクラスで使用するデータメンバーの名前を文字列で指定できます。
class Person: __slots__ = 'name' def __init__(self, name: str) -> None: self.name = name
使用するデータメンバーが複数存在する場合は、タプルやリストなどにまとめて指定します。
class Person: __slots__ = 'name', 'age' def __init__(self, name: str, age: int) -> None: self.name = name self.age = age
効果
__slots__を使用することで以下のような効果があります。
軽量化 + 高速化
__slots__を定義することで__dict__や__weakref__を自動生成しなくなります。それによりクラスを軽量化することができます。
試しに通常のクラスとデータメンバーを指定したクラスのサイズを比較してみます。
通常
class Person: def __init__(self, name: str, age: int) -> None: self.name = name self.age = age print(sys.getsizeof(Person))
実行結果
1072
データクラスを指定
class Person: __slots__ = 'name', 'age' def __init__(self, name: str, age: int) -> None: self.name = name self.age = age print(sys.getsizeof(Person))
実行結果
904
__slots__を定義するだけで100バイト以上軽量化することができました。また、属性の検索速度も大幅に改善されるようです。
ただし、__dict__や弱参照をサポートしていない点には注意してください。
動的な属性の追加の制限
__slots__を定義したクラスでは、動的に属性を追加することができなくなります。
一見デメリットのように感じるかもしれませんが、属性を後から追加する予定がないクラスの場合ではむしろ安全性が増します。
class Person: __slots__ = 'name', 'age' def __init__(self, name: str, age: int) -> None: self.name = name self.age = age mike = Person('Mike', 20) # __slots__にない属性を追加 mike.gender = 'man'
実行結果
Traceback (most recent call last): File "main.py", line 13, in mike.gender = 'man' AttributeError: 'Person' object has no attribute 'gender'
これにより変数名間違いなどの心配もなくなります。
まとめ
この記事では、クラスのデータメンバーを明示的に指定する方法を解説しました。
__slots__を使うことでクラスを「軽量化」+「高速化」することができます。__dict__や弱参照を使わないかつ、動的に変数を追加しない場合は積極的に使っていきましょう!
それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ


