__init__ を呼び出さずにクラスをインスタンス化する方法はありますか?
質問
コンストラクタの
__init__
を回避する方法はありますか?
例です。
class A(object):
def __init__(self):
print "FAILURE"
def Print(self):
print "YEHAA"
ここで
A
. これは次のように見えますが、この構文は正しくありません。
a = A
a.Print()
EDITです。
さらに複雑な例です。
オブジェクトがあるとします
C
があり、その目的は1つのパラメータを保存し、それを使って計算を行うことです。しかし、パラメータはそのまま渡されるのではなく、巨大なパラメータファイルに埋め込まれています。それは次のようなものです。
class C(object):
def __init__(self, ParameterFile):
self._Parameter = self._ExtractParamterFile(ParameterFile)
def _ExtractParamterFile(self, ParameterFile):
#does some complex magic to extract the right parameter
return the_extracted_parameter
次に、そのオブジェクトのインスタンスをダンプしてロードしたいと思います。
C
. しかし、このオブジェクトをロードするとき、私は単一の変数
self._Parameter
という変数しかなく、パラメータファイルを期待しているためコンストラクタを呼び出すことができません。
@staticmethod
def Load(file):
f = open(file, "rb")
oldObject = pickle.load(f)
f.close()
#somehow create newObject without calling __init__
newObject._Parameter = oldObject._Parameter
return newObject
つまり、パラメータファイルを渡さずにインスタンスを作成することはできないのです。しかし、私の場合、それはパラメータファイルではなく、メモリ上に持ち運んだり、ディスクに保存したりしたくないような巨大なデータのゴミです。
のインスタンスを返したいので
C
のインスタンスを返したいので
Load
どうにかしてコンストラクタを呼び出す必要があります。
OLD EDITです。
より複雑な例で、説明すると なぜ という質問をしているのです。
class B(object):
def __init__(self, name, data):
self._Name = name
#do something with data, but do NOT save data in a variable
@staticmethod
def Load(self, file, newName):
f = open(file, "rb")
s = pickle.load(f)
f.close()
newS = B(???)
newS._Name = newName
return newS
見ての通り
data
はクラス変数に格納されていないので、これを
__init__
. もちろん、単純に格納することもできますが、データが巨大なオブジェクトで、常にメモリ上に持ち歩くことも、ディスクに保存することもしたくない場合はどうすればよいでしょうか?
どのように解決するのですか?
あなたは
ができます。
回避する
__init__
を呼び出すことで
__new__
を直接呼び出します。そして、指定された型のオブジェクトを作成し、代替のメソッドとして
__init__
. これは、何かというと
pickle
はそうするでしょう。
しかし、まず非常に強調したいのは、それはあなたが
はいけません。
を行い、あなたが何を達成しようとしているにせよ、より良い方法があり、そのうちのいくつかは他の回答で言及されています。特に
悪い
を呼び出すのをスキップするのは悪い考えです。
__init__
.
オブジェクトが作成されるとき、多かれ少なかれこのようなことが起こります。
a = A.__new__(A, *args, **kwargs)
a.__init__(*args, **kwargs)
2番目のステップをスキップすることができます。
ここで、なぜあなたが
をしてはいけないのか
を行う必要があります。
の目的は
__init__
はオブジェクトを初期化し、すべてのフィールドを埋め、そして確実に
__init__
メソッドが呼び出されるようにします。とは
pickle
では、オブジェクトに関連するすべてのデータを保存しようとするので例外です (
任意の
フィールド/インスタンス変数を含む) を保存しようとするので、例外となります。
__init__
によって設定されたものはpickleによって復元されるので、再度呼び出す必要はありません。
もし
__init__
をスキップして別のイニシャライザを使用すると、一種のコードの重複が発生します。インスタンス変数が埋められる場所が2つあり、イニシャライザの1つでその1つを見逃したり、誤って2つのフィールドを異なる動作にすることは容易いことです。このため、微妙なバグが発生する可能性があり、それを追跡するのはそれほど簡単ではありません。
を知る必要があります。
を知る必要があります)、コードのメンテナンスがより困難になります。言うまでもなく、継承を使用している場合はさらに大きな混乱に陥ります。問題は継承の連鎖を上がっていくことになり、この代替の初期化子を連鎖の上のあらゆる場所で使用しなければならないからです。
また、そうすることで、Pythonのインスタンス生成をオーバーライドして、独自のものを作ることになります。Pythonはすでにあなたのためにそれをうまく行っており、それを再発明する必要はありませんし、あなたのコードを使用する人々を混乱させるでしょう。
代わりに何をするのがベストか、ここにあります。
単一の
__init__
メソッドを使用します。このメソッドは、クラスのすべてのインスタンス化に対して呼び出され、すべてのインスタンス変数を適切に初期化します。初期化の異なるモードでは、2つのアプローチのどちらかを使用します。
-
の異なるシグネチャをサポートする。
__init__
をサポートし、オプションの引数を使用することでケースを処理します。 -
代替コンストラクタとして機能する、いくつかのクラスメソッドを作成します。それらがすべて通常の方法でクラスのインスタンスを作成することを確認します。
__init__
), は、Roman Bodnarchuk が示したように のように、追加作業や何かを実行しながら すべてのデータをクラスに渡すとよいでしょう(そして__init__
がそれを処理する)のがベストですが、それが不可能だったり不便だったりする場合は、インスタンスが生成された後にいくつかのインスタンス変数を設定し、そのインスタンスを__init__
が初期化を終えた後に、いくつかのインスタンス変数を設定することができます。
もし
__init__
がオプションのステップを持つ場合 (たとえば
data
を処理するようなもの)、それをオプションの引数にするか、処理を行う通常のメソッドを作るか...あるいはその両方が可能です。
関連
-
[解決済み] AndroidでPythonを実行する方法はありますか?
-
[解決済み] Pythonで複数行のコメントを作成する方法はありますか?
-
[解決済み] リストの要素を値で削除する簡単な方法はありますか?
-
[解決済み] スレッドを強制終了させる方法はありますか?
-
[解決済み] ベースクラスのコンストラクタを呼び出す際のルールは?
-
[解決済み] 抽象的なクラスをインスタンス化することはできますか?
-
[解決済み] init__ 内でクラス関数を呼び出す
-
[解決済み] PythonでSVGからPNGに変換する
-
[解決済み] オブジェクトのリストに特定の属性値を持つオブジェクトが含まれているかどうかをチェックする
-
[解決済み] PythonのRequestsモジュールを使ってWebサイトに "ログイン "するには?
最新
-
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 2.7サポート終了?
-
[解決済み] Pandasの'Freq'タグにはどのような値が有効ですか?
-
[解決済み] オブジェクトのリストに特定の属性値を持つオブジェクトが含まれているかどうかをチェックする
-
[解決済み] tensorflowのCPUのみのインストールでダイナミックライブラリ 'cudart64_101.dll' を読み込めなかった
-
[解決済み] subprocess.run()の出力を抑制またはキャプチャするには?
-
[解決済み] Python Logging でログメッセージが2回表示される件
-
[解決済み] Pythonで、ウェブサイトが404か200かを確認するためにurllibをどのように使用しますか?
-
[解決済み] Pythonの検索パスを他のソースに展開する
-
[解決済み] Django filter queryset __in for *every* item in list
-
[解決済み] Alembicアップグレードスクリプトでインサートやアップデートを実行するにはどうすればよいですか?