[解決済み] Python (およびPython C API)。new__ と __init__ の比較
質問
これから質問する内容は、重複しているようですが
Pythonの__new__と__init__の使い分け?
の実用的な違いは何なのか、私にはまだはっきりしません。
__new__
と
__init__
は
慌てて言う前に
__new__
はオブジェクトを作成するためのものであり
__init__
はオブジェクトを初期化するためのものであることをはっきりさせておきましょう。
それはわかった。
実際、この区別は私にとって非常に自然なことです。なぜなら、私はC++で
新しい配置
があり、同様にオブジェクトの割り当てを初期化から分離しています。
は Python C API チュートリアル ではこのように説明されています。
新しいメンバは 作成(初期化とは違う)する オブジェクトの作成を担当します。これは Pythonでは
__new__()
メソッドとして公開されています。... 新しいメソッドを実装する理由のひとつは、インスタンス変数の初期値を確保するためです。 インスタンス変数 .
そうそう - 私
を得る
何
__new__
が行っていることですが、それにもかかわらず、私は
まだ
は、なぜそれがPythonで有用なのか理解できません。 与えられた例では
__new__
は、インスタンス変数の初期値を保証したい場合に便利です。まあ、それはまさに
__init__
がそうするのでは?
C API チュートリアルでは、新しい Type ("Noddy") が作成され、その Type の
__new__
関数が定義されています。 Noddy 型には、以下のような文字列メンバがあります。
first
という文字列メンバがあり、この文字列メンバはこのように空文字列で初期化されます。
static PyObject * Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
.....
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
.....
}
ただし
__new__
メソッドが定義されていない場合、私たちは
PyType_GenericNew
を使用する必要があります。これは単にインスタンス変数のメンバをすべて NULL に初期化するだけです。 つまり
__new__
メソッドの唯一の利点は、インスタンス変数がNULLではなく空の文字列として始まることです。
しかし、なぜこれが役に立つのでしょうか。インスタンス変数がデフォルト値で初期化されていることを確認することに関心があるのなら、単に
__init__
メソッドで行うことができたのに。
どのように解決するには?
この違いは主にmutable型とimmutable型で発生します。
__new__
は
タイプ
を最初の引数として受け取り、(通常)その型の新しいインスタンスを返します。したがって、mutable型とimmutable型の両方での使用に適しています。
__init__
は
インスタンス
を第一引数として受け取り、そのインスタンスの属性を変更します。これは不変型には不適切で、作成後に
obj.__init__(*args)
.
の振る舞いを比較してみましょう。
tuple
と
list
:
>>> x = (1, 2)
>>> x
(1, 2)
>>> x.__init__([3, 4])
>>> x # tuple.__init__ does nothing
(1, 2)
>>> y = [1, 2]
>>> y
[1, 2]
>>> y.__init__([3, 4])
>>> y # list.__init__ reinitialises the object
[3, 4]
なぜ別々なのかというと(単純な歴史的理由は別として)。
__new__
メソッドは、正しく動作させるために多くの定型文を必要とします (最初のオブジェクトの作成、そして最後にオブジェクトを返すことを忘れないように)。
__init__
メソッドは、対照的に、設定する必要がある属性を設定するだけなので、非常にシンプルです。
はさておき
__init__
メソッドを書くのが簡単であることや、前述の mutable と immutable の区別は別として、この分離を利用して、親クラスの
__init__
で絶対必要なインスタンス不変量を設定することで、 サブクラスで親クラス __new__
. しかし、これは一般的にはあまり良い方法ではありません。
__init__
メソッドを呼び出す方がより明確です。
関連
-
Python機械学習Githubが8.9Kstarsに達したモデルインタープリタLIME
-
[解決済み】「RuntimeError: dictionary changed size during iteration」エラーを回避する方法とは?
-
[解決済み】numpy: true_divide で無効な値に遭遇
-
[解決済み] staticmethodとclassmethodの違いについて
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] __init__.py は何のためにあるのですか?
-
[解決済み] Pythonでシングルトンを作成する
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
ピロウズ画像色処理の具体的な活用方法
-
pythonサイクルタスクスケジューリングツール スケジュール詳解
-
Pythonの学習とデータマイニングのために知っておくべきターミナルコマンドのトップ10
-
Pythonコードの可読性を向上させるツール「pycodestyle」の使い方を詳しく解説します
-
PythonでECDSAを実装する方法 知っていますか?
-
[解決済み】numpyの配列連結。"ValueError:すべての入力配列は同じ次元数でなければならない"
-
[解決済み】socket.error: [Errno 48] アドレスはすでに使用中です。
-
[解決済み] なぜ __init__() は常に __new__() の後に呼び出されるのですか?
-
[解決済み] 配置換え」にはどんな使い方があるのか?
-
[解決済み】Pythonでimmutableオブジェクトを作るには?