これは魅力的ですが、これをクラスのコンストラクターと呼ぶのは正しくありません。それはコンストラクタのように見えるので魅力的です(慣例により、
__init__
はクラスに定義された最初のメソッドです)、1つのように動作します(クラスの新しく作成されたインスタンスで実行される最初のコードです)、そして1つのようにも聞こえます(「init」は確かにコンストラクターのような性質を示唆しています)。間違っています。オブジェクトは__init__
が呼び出されるまでに既に構築されており、クラスの新しいインスタンスへの有効な参照が既にあるためです。
__init__
が呼び出されるまでにオブジェクトが既に構築されているため、__init__
をconstructorとして呼び出すことは正しくないことを引用しています。だが! constructorは、インスタンスのデータメンバーを初期化するために本質的に使用されるため、オブジェクトが構築された後にのみ呼び出されるという印象を受けていましたconstructorが呼び出されるまでにオブジェクトが存在しなかった場合、意味がありませんか? (C++/Javaのバックグラウンドから来ています)
クラスFoo
がある場合:
Foo()
はconstructorですFoo.__init__()
はinitializerですFoo.__new__()
は、アロケーターPythonオブジェクトの構築は、単に新しいインスタンスを割り当てた後に、そのインスタンスを初期化することです。
個人的には、「__init__
はコンストラクターではありません」ということは、髪の毛を細かく分割するものだと思います。
__init__
は、新しいオブジェクトが要求されたときに呼び出されます。オブジェクトの通常の操作に必要な不変条件が設定されるように、引数を使用して新しいオブジェクトに属性を割り当てることになっています。オブジェクトは、__init__
のコードが実行を開始するまでに、属性を格納するための有効な既存の場所です。 通常、新しいオブジェクトには、__init__
のコードが実行を開始した時点で既に定義されている属性はありません(すべてのオブジェクトが所有するものを除く)。
新しいオブジェクトが要求されると、C++コンストラクターが呼び出されます。オブジェクトの通常の操作に必要な不変条件が設定されるように、引数を使用して新しいオブジェクトのフィールドに割り当てることが想定されています。オブジェクトは、コンストラクターのコードが実行を開始するまでにフィールドを保存するための有効な既存の場所です。 コンストラクター内のコードの実行が開始されると、新しいオブジェクトにはすべての宣言済みフィールドが既にありますが、それらにはゴミが含まれています。
Javaコンストラクターは、新しいオブジェクトが要求されたときに呼び出されます。引数を使用して、新しいオブジェクトのフィールドに割り当て、オブジェクトの通常の操作に必要な不変条件が設定されます。オブジェクトは、コンストラクターのコードが実行を開始するまでにフィールドを格納する有効な既存の場所です。コンストラクターのコードが実行を開始すると、新しいオブジェクトにはすべての宣言済みフィールドがあります。デフォルト値
__init__
メソッドとC++/Javaコンストラクターの主な違いは、私が強調した最後の文にあります。これは、Java/C++の静的な性質とPythonの動的な性質の違いにすぎません。同じWordで参照してはならない根本的に異なる概念を呼び出すことを保証するものではないと思います。
Pythonistaが__init__
をコンストラクターとして参照したくない主な理由は、C++/Javaコンストラクターの人々thinkが「新しいオブジェクトを作成する」というのは、あなたがそれらを呼び出すときに彼らがするように見えるからです。ただし、コンストラクターを呼び出すと、実際に2つのことが行われます。新しいオブジェクトが作成され、コンストラクターが呼び出されて初期化されます。 C++/Javaでは、「新規オブジェクトの作成」部分は見えませんが、Python(__new__
メソッド経由)で公開/カスタマイズできます。
したがって、__init__
メソッドの役割はC++/Javaコンストラクターの役割に非常に似ていますが、一部の人々は、「__init__
はコンストラクタではありません」。
コンストラクター戻り値インスタンスであり、失敗する可能性があります。だが __init__
はインスタンスを返しません。ときでさえ __init__
発生および例外、__del__
は、インスタンスを削除するために呼び出されます。
これはここで見ることができます:
class A(object):
def __init__(self):
raise ValueError
def __del__(self):
print "Called"
def main():
try:
a = A()
except ValueError, e:
print "ValueError"
if __== '__main__':
main()
__new__
一方、インスタンスを返します。
http://www.programiz.com/article/python-self-why から
__init__()
はコンストラクタではありません[..] 1つの重要な結論[..]は、
__init__()
はコンストラクタではないということです。多くの素朴なPythonプログラマーは、オブジェクトを作成するときに__init__()
が呼び出されるため、プログラマと混同されます。詳細な検査により、__init__()
の最初のパラメーターオブジェクト自体(オブジェクトは既に存在します)関数__init__()
は、オブジェクトが作成された直後に呼び出され、オブジェクトの初期化に使用されます。技術的に言えば、コンストラクターはオブジェクト自体を作成するメソッドです。 Pythonでは、このメソッドは
__new__()
です。このメソッドの一般的な署名は
__new__(cls, *args, **kwargs)
ベンから与えられた回答に関して、私はここで、ほとんどの言語はその定義に従っていないと主張します(完全に)。
さらに:
__new__()
が呼び出されると、クラス自体が最初の引数として自動的に渡されます。これが、上記の署名のcls
の目的です。繰り返しますが、self
と同様に、cls
は単なる命名規則です。さらに、_*args
_および_**kwargs
_は、Pythonのメソッド呼び出し中に任意の数の引数を取得するために使用されます。
__new__()
を実装する際に覚えておくべき重要なことは次のとおりです。
__new__()
は常に__init__()
の前に呼び出されます。- 最初の引数は、暗黙的に渡されるクラス自体です。
__new__()
から常に有効なオブジェクトを返します。必須ではありませんが、それがポイントです。
ボトムライン(私にとって):__new__()
は、__init__()
ではなく、コンストラクターのように見えますが、すべての実用的な手段で、__init__()
は、ほとんどの人がコンストラクターが考えるものの一部です行う。
John Zelleの「Programming Python:Introduction to Computer Science」では、「特別な方法__init__
はオブジェクトコンストラクターです。 Pythonはこのメソッドを呼び出して新しいオブジェクトを初期化します。__init__
は、オブジェクトのインスタンス変数の初期値を提供することです。」