Pythonのクラスコンストラクター。__new__と__init__

2021/01/26PythonPythonの基本

記事内に広告が含まれています。

PythonのClass(クラス)にはコンストラクターと呼ばれる特別なメソッドがあります。

コンストラクターはクラスが生成されるタイミングで自動で呼び出されるメソッドでクラス自身の設定を変更したり、インスタンス変数の初期化などを行います。

スポンサーリンク

Pythonのコンストラクター

Pythonのコンストラクターには__new__()と__init__()の2つのコンストラクターが存在します。

__new__()と__init__()は呼び出されるタイミングが異なり、そこから初期化する役割が変わってきます。

コンストラクター__new__()

コンストラクターの__new__()はインスタンスオブジェクトが生成される前に呼ばれます。

クラス自体の初期化を行うのに使います。

後述のクラスコンストラクター__init__()より前に自動でコールされます。

class MyClass():
    def __new__( cls ) :
        self = super().__new__( cls )
        print( "__new__()  myId={}".format( id( self )))
        return self 

通常は親クラス(Object)のコンストラクターの実行結果を戻り値として返します。
(戻り値は必須です。)

コンストラクター__init__()

コンストラクタのー__init__()はインスタンスオブジェクトが生成された後に呼ばれます。

class MyClass():
    def __init__( self ) :
        print( "__init__()  myId={}".format( id( self )))
        self.myVariable = 10

インスタンス自身を第1引数に受け取り、インスタンスの初期化などを行います。

__new__()と__init__()を呼び出してみる

実際にクラスとインスタンスを生成して__new__()と__init__()を呼び出してみます。

class MyClass():
    def __new__( cls ) :
        self = super().__new__( cls )
        print( "__new__()  myId={}".format( id( self )))
        return self

    def __init__( self ) :
        print( "__init__()  myId={}".format( id( self )))
        self.myVariable = 10

cl1 = MyClass()
cl2 = MyClass()

上記の実行結果は

__new__()  myId=1824388893832
__init__()  myId=1824388893832
__new__()  myId=1824388893640
__init__()  myId=1824388893640

となり、__new__()が呼ばれ、そのあとで__init__()が呼ばれていることがわかります。

#コンストラクタ__new__ __init__
#インスタンスオブジェクトが生成される前に呼ばれます。 インスタンスオブジェクトが生成された後に呼ばれます。

__new__()の使用例

__new__()も__init__()も自動で最初に呼ばれるならどちらを使っても良いのでは?と思うこともあります。

でも__new__()でしかできないこともあるので、その例を1つ挙げておきます。

今回の例はデザインパターンの「Singleton」パターンを実装してみます。

「Singleton」パターンはシステム内でそのオブジェクトが1つしかないことを保証するデザインパターンです。

通常はクラスに対して「new」をするとそのたびにインスタンスが生成されるのですが、「Singleton」パターンはすでにそのクラスが一度でもインスタンス化されていた場合は、新たにインスタンス化せずに保持している唯一のインスタンスを返す処理です。

class mySingleton:
    __instance = None

    def __new__( cls ) :
        if cls.__instance is None :    #クラスが1度もインスタンス化されていない時
            cls.__instance = super().__new__( cls )  #クラスを生成しセーブ
            print( "__new__" )

        return cls.__instance

    def __init__( self ) :
        print( "__init__" )

if __name__ == '__main__':
    cl1 = mySingleton()  # __new__と__init__が呼ばれる
    cl2 = mySingleton()  # __init__しか呼ばれない
    print( "cl1  Id={}".format( id( cl1 )))
    print( "cl2  Id={}".format( id( cl2 )))

上記の例は__new__でクラスが1度でも生成されたかチェックを行い、されてない時のみクラスを生成します。

実行結果は

__new__
__init__
__init__
cl1  Id=1626399067336
cl1  Id=1626399067336

となり生成した複数回インスタンス化しても1つのインスタンスしか生成されていないことがわかります。

まとめ

Pythonのコンストラクターには__new__()と__init__()の2つのコンストラクターが存在します。

__new__() __init__()
インスタンスオブジェクトが生成される前に呼ばれます。 インスタンスオブジェクトが生成された後に呼ばれます。
システムトラストでは一緒に働いていただける仲間を募集中です。
記事内に広告が含まれています。
株式会社システムトラスト

システムトラストでは、システムエンジニア、プログラマーなどを随時募集中です。気軽にご相談ください。

お問合せ