CodeReviewのこの投稿 に基づきます。
クラスFoo
in Python(3)、これにはもちろん__init__()
メソッドが含まれます。このクラスはいくつかのプロンプトを起動し、その処理を行います。Foo
をリセットできるようにしたいので、手順を最初からやり直すことができます。
推奨される実装は何ですか?
__init__()
メソッドを再度呼び出す
_def reset(self):
self.__init__()
_
または新しいインスタンスを作成しますか?
_def reset(self):
Foo()
_
Foo
の新しいインスタンスを作成しても、reset
が何度も呼び出された場合にパフォーマンスに影響する可能性のあるものが残るかどうかはわかりません。一方、すべての属性が__init__()
で(再)定義されているわけではない場合、__init__()
に副作用がある可能性があります。
これを行うための好ましい方法はありますか?
どちらも正しいですが、セマンティクスは同じ方法で実装されていません。
インスタンスをリセットできるようにするには、これを記述します(___init__
_は特別なメソッドであるため、___init__
_からカスタムメソッドを呼び出すことを好みますが、これは主に好みの問題です) :
_class Foo:
def __init__(self):
self.reset()
def reset(self):
# set all members to their initial value
_
そのように使用します:
_Foo foo # create an instance
...
foo.reset() # reset it
_
クラスが特別なメソッドを実装する必要がないため、ゼロから新しいインスタンスを作成するのは実際には簡単です。
_Foo foo # create an instance
...
foo = Foo() # make foo be a brand new Foo
_
古いインスタンスは、他で使用されていない場合、ガベージコレクションされます
両方の方法は、すべての初期化が___init__
_で行われるnormalクラスに使用できますが、カスタマイズされた特別なクラスには2番目の方法が必要です作成時に___new__
_を使用します(不変クラスなど)。
ただし、次のコードに注意してください。
_def reset(self):
Foo()
_
will not必要なことを行います。新しいインスタンスを作成するだけで、メソッドの最後にスコープ外になるため、すぐに削除します。 self = Foo()
でさえ、ローカル参照のみを設定しますが、ローカル参照はメトスの終わりに同じ範囲外になります(そして新しいインスタンスが破棄されます)。
クラス属性で作業するインスタンスを保持できます。クラスをリセットするたびに、新しいインスタンスをその属性に再割り当てします。このアプローチの実装方法は次のとおりです。
_class Foo:
instance = None # The single instance
def __init__(self, ...):
# Initialize the instance if Foo.instance does not exist, else fail
if type(self).instance is None:
# Initialization
type(self).instance = self
else:
raise RuntimeError("Only one instance of 'Foo' can exist at a time")
@classmethod
def reset(cls):
cls.instance = None # First clear Foo.instance so that __init__ does not fail
cls.instance = Foo(...) # Now the initialization can be called
_
その後、単に_Foo.instance
_を参照するだけでインスタンスにアクセスできます。
クラスメソッドとしてreset
を選択したため、_@classmethod
_で装飾されています。このデコレーターを使用すると、Foo.reset()
を呼び出すことでインスタンスをリセットでき、cls
パラメーターがメソッドに自動的に渡されます。
私はあなたが提案するものよりもこのアプローチ(多かれ少なかれシングルトンパターンです)を好む、なぜならあなたの状況では、をしたいので、Foo
の単一のインスタンスを持つことが論理的に見えるからですリセットしたがって、単一のインスタンスの使用を「強制」するのはかなり直感的です。
一方、クラスの外部にインスタンスを持ち、定義されたreset
インスタンスメソッドを使用できます。
_def reset(self):
self.__init__()
_
しかし、これはあまりうまくいかないかもしれません。 ___init__
_メソッド以外の属性を設定するとします。 ___init__
_を呼び出しても、これらの属性はリセットされません。したがって、インスタンスは期待どおりにリセットされません。単一のインスタンスを保持し、それを真新しいインスタンスに再割り当てすると、完全にクリーンになることが確実になります。
あなたが呼ぶものについて「新しいインスタンスを作成する」、それは多かれ少なかれ私が選んだものですが、問題はそれをどこに保存するかです。クラス自体を暖かくすることは理にかなっていると思います。
ちなみに、このソリューションでは、一度に1つのFoo
インスタンスのみが参照され、新しいインスタンスを作成すると以前の参照が逆参照されるため、パフォーマンスの問題は発生しません(「メモリリーク」など)。 1。