Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

【Python入門】Pythonのクラスの__new__()メソッドについて基本をわかりやすく解説

初心者に向けて、Pythonのクラスの中の__new__()メソッドについてその基本をわかりやすく解説

前回の記事ではPythonの特殊メソッドの1つでクラス定義の中で使われる__init__()メソッドについて解説を書きました。それが下の記事です。

【Python入門】クラスの__init__()メソッドの基本についてわかりやすく解説

今回は、その__init__()メソッドと連携して機能する特殊メソッドの__new__()メソッドについてその基本的な考え方と使い方を解説します。

プログラミング言語の人気オンラインコース

前提知識:__init__()メソッドについて

まず前提知識として__init__()メソッドの初歩的知識があると__new__()メソッドについても少し理解がしやすくなるので、__init__()についての解説「【Python入門】クラスの__init__()メソッドの基本についてわかりやすく解説」を読んでみてください。

公式ドキュメント

Python公式ドキュメントでは次のように解説されています。

object.__new__(cls[, …])

クラス cls の新しいインスタンスを作るために呼び出されます。 __new__() は静的メソッドで (このメソッドは特別扱いされているので、明示的に静的メソッドと宣言する必要はありません)、インスタンスを生成するよう要求されているクラスを第一引数にとります。残りの引数はオブジェクトのコンストラクタの式 (クラスの呼び出し文) に渡されます。 __new()__ の戻り値は新しいオブジェクトのインスタンス (通常は cls のインスタンス) でなければなりません。

典型的な実装では、クラスの新たなインスタンスを生成するときには super().__new__(cls[, …]) に適切な引数を指定してスーパクラスの __new__() メソッドを呼び出し、新たに生成されたインスタンスに必要な変更を加えてから返します。

もし __new__() が オブジェクトの作成中に呼び出され、cls のインスタンスを返した場合には、 __init__(self[, …]) のようにして新しいインスタンスの init() が呼び出されます。このとき、 self は新たに生成されたインスタンスで、残りの引数はオブジェクトコンストラクタに渡された引数と同じになります。

__new__() が cls のインスタンスを返さない場合、インスタンスの __init__() メソッドは呼び出されません。

__new__() の主な目的は、変更不能な型 (int, str, tuple など) のサブクラスでインスタンス生成をカスタマイズすることにあります。

相変わらずよくわかりません。

そこで以下、クラスに__new__()メソッドがない場合とある場合に分けて順番に理解していきましょう。

クラスに、__new__()メソッドがない場合

class E:
   
    def __init__(self, name_var, country_var):
        self.name = name_var
        self.country = country_var
        
e = E("Tom", "USA")        
e.name
e.country

このコードにおける、クラスE中の__init__()メソッドは、すでに作成されているクラスEのインスタンスに対して初期設定を施すためのメソッドです。

詳しくは、記事「【Python入門】クラスの__init__()メソッドの基本についてわかりやすく解説」をご覧ください。また、Udemyのおすすめ動画講座、現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイルでもわかりやすく解説されています。

重要なのは、この__init__()メソッドが実行される前に、「すでにクラスのインスタンスが作成されている」ことです。

では、どうやってインスタンスが作成されているのでしょうか?それは、object.__new__()メソッドが自動的に実行されることでインスタンスが作られているのです。それによって作成されたインスタンスが、__init__()メソッドに渡されるという仕組みになっています。

わざわざ、クラスの中で

object.__new__(~)

と書かなくても、勝手に自動的に実行されているのです。上記公式説明の中で

__new__() は静的メソッドで (このメソッドは特別扱いされているので、明示的に静的メソッドと宣言する必要はありません

と書かれているのはそういうことです。

このように、クラス定義の中でわざわざ__new__()メソッドを書かなくても自動的にそれが実行されてインスタンスが作られることがわかりました。

では、あえて明示的に、

def __new__(略):

と、__new__()メソッドを定義しなおした場合はどうなるのでしょうか?以下で解説します。

def __new__()と明示的に定義した場合

次のコードを見てください。

実行結果は、

2763856304320
 クラスEのID: 2763856304320,
 インスタンスのID: 2763864293136,        
 var1: Tom,
 var2: USA
第1仮引数selfのID: 2763864293136
'Tom'

'USA'

となります。

このコードの処理の流れで注目すべきは、次の諸点です。

  • def __new__()を定義すると、def __init__()よりも前にそれが実行される
  • def __new__()を定義した場合は、その中でobject.__new__()またはsuper().__new__()を明示的に実行してインスタンスを作成し、それをreturn文で返す設計にする。こうしてインスタンスが返されると、def __init__()が次に実行される。
  • def __new__()の第1仮引数clsには、そのクラス(ここではE)そのものが入る。実行結果中のdir(E)で示されるID番号と「クラスEのID: 2763856304320」のID番号が一致していることに着目してください。
  • e =E()で指定した実引数は、そのままdef __new__()の第2引数以下に渡される
  • def __new__()の第1仮引数clsが、def __init__()の第1仮引数selfへと渡される。実行結果の中の、「インスタンスのID: 2763864293136」と「第1仮引数selfのID: 2763864293136」のID番号が一致していることに着目してください。
  • def __new__()の第2仮引数以下が、def __init__()の第2仮引数以下へ渡される

これが__new__()メソッドの基本的な考え方・使い方となります。こうしたクラスの中の特殊なメソッドについても、Udemyの動画講座の現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイルや、【完全初心者向け】絶対に挫折させないPython入門講座では動画ならではのわかりやすさがあります。

また次のような動画講座もオススメです。

愛を分かち合いましょう