Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What is going on with this article?
@fumitoh

__slots__を定義する場合の継承に関する注意点

More than 1 year has passed since last update.

通常、class文によって定義されたクラスのインスタンスは自由にデータメンバを追加することができ、属性の値は__dict__メンバ変数に保存されていますが、クラスに__slots__を定義し、明示的にデータメンバを列挙すると、そのクラスのインスタンスは、__dict__を持たなくなり、列挙されていないデータメンバを持てなくなります。
__dict__を持たない分、メモリが節約でき、またデータメンバへのアクセスも若干早くなります。
ただ、__slots__を定義する際、いくつか注意点があります。
(参考: https://docs.python.org/3/reference/datamodel.html#slots)

1. クラスに__slots__を定義する場合、その基底クラスは全て__slots__を持つ必要がある。

次の例のように、基底クラスに__slots__が定義されていないと、__dict__が生成されてデータメンバが追加可能になり、__slots__を定義した意味が無くなります。


class A:
    pass

class B(A):
    __slots__ = ('foo',)
>>> b = B()

>>> b.bar = 3     # __slots__を定義しているにも関わらず属性が定義できてしまう

>>> b.__dict__    # __dict__が生成されてしまっている
{'bar': 3}

基底クラスに__slots__を定義すると、この問題は解決します。


class A:
    __slots__ = ()    # 空の__slots__を定義する

class B(A):
    __slots__ = ('foo',)

>>> b = B()

>>> b.bar = 3     
AttributeError: 'B' object has no attribute 'bar'

>>> b.__dict__   
AttributeError: 'B' object has no attribute '__dict__'

2. 基底クラスの__slots__に同名の変数の定義があると、重複してデータメンバが確保されていまう。
無駄なアクセスできない変数が生成されてまいます。将来的にはエラーとなるようチェックをかけるかもしれないということですが、Python 3.7時点ではエラーにはなりません。

class A:
    __slots__ = ('foo',)

class B(A):
    __slots__ = ('foo',)
>>> import sys

>>> a = A()

>>> b = B()

>>> sys.getsizeof(a)
48

>>> sys.getsizeof(b)
56

3. 多重継承により、空でない__slots__を持つ複数の基底クラスは持てない。
この制約はエラーになるのですぐにわかりますが、下記のコードを実行するとTypeError: multiple bases have instance lay-out conflictとなります。

class A:
    __slots__ = ('foo',)

class B:
    __slots__ = ('bar',)

class C(A, B):
    __slots__ = ('baz',)

次のように、どちらか一方は空の__slots__となるようにクラスの設計を考え直す必要があります。

class A:
    __slots__ = ()

class B:
    __slots__ = ('foo', 'bar')

class C(A, B):
    __slots__ = ('baz',)

参考: https://stackoverflow.com/questions/472000/usage-of-slots

8
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
fumitoh
Pythonの言語仕様や実装に関する備忘録が中心です。たまに便利なTipsなども投稿します。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
8
Help us understand the problem. What is going on with this article?