サブクラスでの__slot__の継承は、実際にはどのように行われるのですか?
質問
で
スロットのPythonデータモデルリファレンスのセクションで
を使用する際の注意事項のリストがあります。
__slots__
. 1番目と6番目の項目が矛盾しているような気がして徹底的に混乱しています。
1番目の項目
-
がないクラスを継承する場合
__slots__
がない場合は__dict__
属性は は常に にアクセスできるので__slots__
の定義は無意味です。 は意味を持ちません。
6番目の項目です。
-
の動作は
__slots__
宣言の動作は、定義されたクラス内に限定されます。 に限定されます。その結果 サブクラスには__dict__
も定義されていない限り__slots__
(を定義していなければなりません(これは追加のスロットの名前のみを含む必要があります)。 を定義していなければなりません。)
これらの項目は、より良い言葉で表現するか、コードで示すことができるように思えますが、私はこのことについて頭を悩ませ、まだ混乱しています。私は、次のように理解しています。
__slots__
は
を使用することになっています。
であり、私はそれらがどのように機能するかについてより良い把握をしようとしています。
質問です。
どなたか、サブクラス化する際のスロットの継承の条件をわかりやすく説明していただけませんか?
(簡単なコード例があれば助かりますが、必要ありません)。
どのように解決するのですか?
他の方もおっしゃっているように、このように
__slots__
を定義する唯一の理由は、あらかじめ定義された属性のセットを持つ単純なオブジェクトがあり、それぞれが辞書を持ち歩く必要がない場合に、メモリを節約するためです。 これは、もちろん、多くのインスタンスを持つ予定のクラスに対してのみ意味があります。
節約はすぐに明らかにならないかもしれませんが、考えてみてください。
>>> class NoSlots(object): pass
...
>>> n = NoSlots()
>>> class WithSlots(object): __slots__ = 'a', 'b', 'c'
...
>>> w = WithSlots()
>>> n.a = n.b = n.c = 23
>>> w.a = w.b = w.c = 23
>>> sys.getsizeof(n)
32
>>> sys.getsizeof(w)
36
これより、ウィズスロットサイズは
より大きい
であるように見えます。 しかし、それは間違いです。
sys.getsizeof
は辞書のような "オブジェクトコンテンツ" を考慮しないためです。
>>> sys.getsizeof(n.__dict__)
140
dict だけでも 140 バイトかかるので、明らかに "32 bytes" のオブジェクトは
n
は、それぞれのインスタンスに関係するすべてを考慮していないと主張されています。 次のようなサードパーティの拡張機能を使用すると、より良い仕事ができます。
ピンプラー
:
>>> import pympler.asizeof
>>> pympler.asizeof.asizeof(w)
96
>>> pympler.asizeof.asizeof(n)
288
によって節約されるメモリフットプリントをより明確に示しています。
__slots__
このような単純なオブジェクトの場合、200 バイト弱で、オブジェクト全体のフットプリントのほぼ 2/3 にあたります。 最近では、ほとんどのアプリケーションで 1 メガバイトの多寡はそれほど重要ではないので、このことからもわかるように
__slots__
は、一度に数千のインスタンスしか扱わないのであれば、わざわざ使う価値はないということです。しかし、数百万のインスタンスに対しては、非常に重要な違いであることは確かです。また、微小なスピードアップも得られます(小さなオブジェクトに対して
__slots__
):
$ python -mtimeit -s'class S(object): __slots__="x","y"' -s's=S(); s.x=s.y=23' 's.x'
10000000 loops, best of 3: 0.37 usec per loop
$ python -mtimeit -s'class S(object): pass' -s's=S(); s.x=s.y=23' 's.x'
1000000 loops, best of 3: 0.604 usec per loop
$ python -mtimeit -s'class S(object): __slots__="x","y"' -s's=S(); s.x=s.y=23' 's.x=45'
1000000 loops, best of 3: 0.28 usec per loop
$ python -mtimeit -s'class S(object): pass' -s's=S(); s.x=s.y=23' 's.x=45'
1000000 loops, best of 3: 0.332 usec per loop
が、これはPythonのバージョンに多少依存します(これは私が2.5で繰り返し測定した数字です; 2.6では、より大きな相対的利点が
__slots__
に対して
設定
属性が設定されていますが、全くなく、本当に小さな
ディス
のため、利点は
得る
を得るため)。
さて、継承についてですが、インスタンスがディクショナリーであるためには
すべて
クラスもディクテレスインスタンスを持たなければなりません。 ディクテレスインスタンスを持つクラスは
__slots__
を定義するクラス、およびほとんどの組み込み型です(インスタンスがディクテを持つ組み込み型は、関数などの任意の属性を設定することができるインスタンスです)。スロット名の重複は禁止されていませんが、スロットは継承されるため、無駄であり、いくつかのメモリを浪費します。
>>> class A(object): __slots__='a'
...
>>> class AB(A): __slots__='b'
...
>>> ab=AB()
>>> ab.a = ab.b = 23
>>>
このように
a
の上に
AB
インスタンス --
AB
自体はスロットのみを定義しています。
b
を定義するだけで、スロット
a
から
A
. 継承したスロットの繰り返しは禁止されていません。
>>> class ABRed(A): __slots__='a','b'
...
>>> abr=ABRed()
>>> abr.a = abr.b = 23
のようになりますが、少しメモリを浪費します。
>>> pympler.asizeof.asizeof(ab)
88
>>> pympler.asizeof.asizeof(abr)
96
ということで、特に理由はありません。
関連
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] Pythonの@propertyデコレーターはどのように機能するのでしょうか?
-
[解決済み] Pythonのsuper()は多重継承でどう動くのか?
-
[解決済み] collections.defaultdictはどのように機能するのですか?
-
[解決済み】名前が与えられたクラスのすべてのサブクラスを見つけるには?
-
[解決済み] バブルソートの宿題
-
[解決済み] Python 3でバイナリデータを標準出力に書き込むには?
-
[解決済み] PyQtアプリケーションのスレッド化。QtスレッドとPythonスレッドのどちらを使うか?
-
[解決済み] CSVデータを処理する際、1行目のデータを無視する方法を教えてください。
-
[解決済み] pipの依存性/必要条件をリストアップする方法はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] スロットの使い方__?
-
[解決済み] PILからopenCVフォーマットへの変換
-
[解決済み] Djangoで2つの日付の間を選択する
-
[解決済み] Pythonのインスタンス変数とクラス変数
-
[解決済み] Python 2.7サポート終了?
-
[解決済み] データフレームをソートした後にインデックスを更新する
-
[解決済み] 古いバージョンのPythonにおける辞書のキーの並び順
-
[解決済み] pandasのタイムゾーンに対応したDateTimeIndexを、特定のタイムゾーンに対応したナイーブなタイムスタンプに変換する。
-
[解決済み] matplotlib でプロットの軸、目盛、ラベルの色を変更する方法
-
[解決済み] Python Empty Generator 関数