[解決済み] objectクラスのインスタンスに属性を設定できない
質問
というわけで、Pythonで遊んでいるときに この質問 で、これが有効でないことを発見しました。
o = object()
o.attr = 'hello'
により
AttributeError: 'object' object has no attribute 'attr'
. しかし、objectから継承されたクラスであれば、有効である。
class Sub(object):
pass
s = Sub()
s.attr = 'hello'
印刷
s.attr
は期待通りに'hello'を表示します。なぜこのようなことが起こるのでしょうか?Pythonの言語仕様の中で、vanillaオブジェクトに属性を割り当ててはいけないと定めているものは何ですか?
どのように解決するのですか?
任意の属性の割り当てをサポートするために、オブジェクトには
__dict__
が必要です。これはオブジェクトに関連付けられたディクショナリーで、任意の属性を格納することができます。そうでなければ
を置く
を置く場所がありません。
のインスタンスは
object
は
ではない
を持ち歩く
__dict__
-- もしそうなら、恐ろしい循環依存性の問題が起こる前に(というのは
dict
は他のほとんどのものと同じように
object
;-) を継承する場合、これは
を鞍替えすることになります。
のオーバーヘッドを意味します。
多くの
バイトのオーバーヘッドを意味します(基本的に、任意に割り当て可能な属性を持たないすべてのオブジェクトは、dict を持たないし、必要としません)。
たとえば、優れた
pympler
プロジェクト (svn経由で次の場所から入手できます) を使ってみましょう。
ここで
から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
インスタンスは任意の属性を持つことができますが、その柔軟性のためにかなりのスペースコストを支払うことになります。
では、もしあなたが
int
を
一つ
という属性があります。
foobar
...? これは稀なニーズですが、Pythonはこの目的のために特別なメカニズムを提供しています...
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
...ではなく
かなり
のような小さな
int
と同じくらい小さいです。(あるいは、2つの
int
があり、ひとつは
self
と、ひとつは
self.foobar
-- は再割り当て可能です) が、確かに
dint
.
クラスが
__slots__
という特別な属性(文字列の列)がある場合、そのクラスは
class
ステートメント(より正確にはデフォルトのメタクラス。
type
) は
ではなく
は、そのクラスのすべてのインスタンスに
__dict__
(したがって、任意の属性を持つ能力) を持たず、与えられた名前を持つ "slots" (基本的に、それぞれがあるオブジェクトへの1つの参照を保持できる場所) の有限で硬いセットだけです。
失われた柔軟性と引き換えに、インスタンスごとに多くのバイトを得ることができます (おそらく、何十億ものインスタンスが飛び回っている場合のみ意味がありますが、ここでは は の使用例があります)。
関連
-
[解決済み] Pythonで静的なクラス変数は可能ですか?
-
[解決済み] Pythonでオブジェクトが属性を持つかどうかを知る方法
-
[解決済み] オブジェクトの種類を決定しますか?
-
[解決済み] インスタンスのクラス名を取得する?
-
[解決済み] Pythonのクラスはなぜオブジェクトを継承するのですか?
-
[解決済み] Pythonでnullオブジェクトを参照する
-
[解決済み] HTMLのid属性とname属性の違い
-
[解決済み】なぜPythonはこのJSONデータをパースできないのですか?[終了] PythonがこのJSONデータをパースできないのはなぜですか?
-
[解決済み】既存のオブジェクトインスタンスにメソッドを追加する
-
[解決済み] Pandasのデータフレームでタプルの列を分割するにはどうしたらいいですか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Flaskで1時間ごとに関数を実行するようにスケジュールするには?
-
[解決済み] バブルソートの宿題
-
[解決済み] dict を txt ファイルに書き、それを読み取る?
-
[解決済み] pandasのタイムゾーンに対応したDateTimeIndexを、特定のタイムゾーンに対応したナイーブなタイムスタンプに変換する。
-
[解決済み] tensorflowのCPUのみのインストールでダイナミックライブラリ 'cudart64_101.dll' を読み込めなかった
-
[解決済み] Flask でグローバル変数はスレッドセーフか?リクエスト間でデータを共有するには?
-
[解決済み] Python Empty Generator 関数
-
[解決済み] Pythonで、ウェブサイトが404か200かを確認するためにurllibをどのように使用しますか?
-
[解決済み] PySparkでデータフレームのカラムをString型からDouble型に変更する方法は?
-
[解決済み] Pythonの辞書にあるスレッドセーフについて