任意の属性の割り当てをサポート__dict__
するには、オブジェクトにオブジェクトに関連付けられた:dictが必要です。ここに、任意の属性を格納できます。そうでなければ、新しい属性を置く場所がありません。
のインスタンスは-を持ち運びobject
ません__dict__
-もしそうなら、恐ろしい循環依存問題の前に(dict
他のほとんどすべてのように、;-から継承するので)object
、これはPythonのすべてのオブジェクトをdictでサドルします、これはオーバーヘッドを意味します現在dictを持っていない、または必要としないオブジェクトごとの多くのバイト数(基本的に、任意に割り当て可能な属性を持たないすべてのオブジェクトはdictを持っていないか、必要としません)。
たとえば、優れたpympler
プロジェクト(ここからsvnを介して取得できます)を使用して、いくつかの測定を行うことができます...:
>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
すべてint
が16バイトではなく144バイトを占めることを望まないでしょう?-)
さて、(何からでも継承して)クラスを作成すると、状況が変わります...:
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
...これ__dict__
が追加されました(さらに、もう少しオーバーヘッドがあります)-dint
インスタンスは任意の属性を持つことができますが、その柔軟性にはかなりのスペースコストがかかります。
では、追加の属性が1つint
だけのsが必要な場合はどうでしょうか...?まれなニーズですが、Pythonはその目的のために特別なメカニズムを提供します...foobar
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
...ではない、かなりのように小さなとしてint
、あなたを気に!(または、2つint
、1つと1つ、self
もう1つはself.foobar
再割り当てできます)が、確かにdint
。よりもはるかに優れています。
クラスに__slots__
特別な属性(文字列のシーケンス)がある場合、class
ステートメント(より正確にはデフォルトのメタクラスtype
)は、そのクラスのすべてのインスタンスに(したがって任意の属性を持つ機能)を備えているわけではなく__dict__
、有限です。 、指定された名前の「スロット」(基本的にはそれぞれがオブジェクトへの1つの参照を保持できる場所)の厳密なセット。
柔軟性が失われる代わりに、インスタンスごとに多くのバイトが得られます(おそらく、無数のインスタンスが活発に機能している場合にのみ意味がありますが、そのユースケースがあります)。
object
タイプは不変であり、新しい属性を追加することはできませんか?これが最も理にかなっているようです。