ホームページ >バックエンド開発 >Python チュートリアル >Pythonの__init__と__new__の違いを詳しく解説
__init__ メソッドとは何ですか?
Python でオブジェクト指向のコードを作成したことがある学生は、__init__ メソッドに精通しているかもしれません。通常、__init__ メソッドはクラス インスタンスを初期化するときに使用されます。例:
# -*- coding: utf-8 -*- class Person(object): """Silly Person""" def __init__(self, name, age): self.name = name self.age = age def __str__(self): return '<Person: %s(%s)>' % (self.name, self.age) if __name__ == '__main__': piglei = Person('piglei', 24) print piglei
これは __init__ の最も一般的な使用法です。ただし、実際には __init__ はクラスをインスタンス化するときに呼び出される最初のメソッドではありません。 Persion(name, age) のような式を使用してクラスをインスタンス化する場合、最初に呼び出されるメソッドは実際には __new__ メソッドです。
__new__ メソッドとは何ですか?
__new__ メソッドは __init__ と同じパラメータを受け入れますが、__init__ はクラス インスタンスが作成された後に呼び出され、__new__ メソッドはこのクラス インスタンスを作成するメソッドです。
# -*- coding: utf-8 -*- class Person(object): """Silly Person""" def __new__(cls, name, age): print '__new__ called.' return super(Person, cls).__new__(cls, name, age) def __init__(self, name, age): print '__init__ called.' self.name = name self.age = age def __str__(self): return '<Person: %s(%s)>' % (self.name, self.age) if __name__ == '__main__': piglei = Person('piglei', 24) print piglei
実行結果:
piglei@macbook-pro:blog$ python new_and_init.py __new__ called. __init__ called. <Person: piglei(24)>
このコードを実行すると、__new__ メソッドの呼び出しが __init__ の前に発生することがわかります。実際、クラスをインスタンス化するときの具体的な実行ロジックは次のとおりです:
1.p = 人物(名前、年齢)
2. まず、name パラメータと age パラメータを使用して Person クラスの __new__ メソッドを実行します。この __new__ メソッドは、通常は super(Persion, cls).__new__(cls) などのインスタンスを返します。 ..) この方法)
3. 次に、このインスタンスを使用して、クラスの __init__ メソッドを呼び出します。前の手順で __new__ によって生成されたインスタンスも、__init__ の self
です。したがって、__init__ と __new__ の主な違いは次のとおりです。
1.__init__ は通常、新しいインスタンスを初期化し、クラス インスタンスの作成後に発生するいくつかの属性の追加や追加の操作の実行などの初期化プロセスを制御するために使用されます。これはインスタンスレベルのメソッドです。
2.__new__ は通常、新しいインスタンスを生成するプロセスを制御するために使用されます。これはクラスレベルのメソッドです。
そうは言っても、__new__ の最も一般的な使用法は何ですか?
__new__ の役割
Python の公式ドキュメントによると、__new__ メソッドは主に、一部の不変クラス (int、str、tuple など) を継承するときに、これらのクラスのインスタンス化プロセスをカスタマイズする方法を提供するために使用されます。カスタム メタクラスの実装もあります。
まず、最初の関数を見てみましょう。具体的には、例として int を使用します。
int を統合することで常に正の整数型が必要な場合は、次のようなコードを書くことができます。
class PositiveInteger(int): def __init__(self, value): super(PositiveInteger, self).__init__(self, abs(value)) i = PositiveInteger(-3) print iしかし、実行してみると、結果はまったく私たちが考えていたものではなく、-3 のままであることがわかります。これは、int のような不変オブジェクトの場合、その __new__ メソッドをオーバーロードすることによってのみカスタマイズできるためです。
これは変更されたコードです:
class PositiveInteger(int): def __new__(cls, value): return super(PositiveInteger, cls).__new__(cls, abs(value)) i = PositiveInteger(-3) print i__new__ メソッドをオーバーロードすることで、必要な機能を実現します。
もう 1 つの関数はカスタム メタクラスに関するものです。実は、私が初めて __new__ に触れたのは、メタクラスをカスタマイズする必要があったからでしたが、スペースの都合上、Python におけるメタクラスと __new__ の関係については次回にお話します。
__new__ を使用してシングルトンを実装します
実際、__new__ メソッドを理解すると、このメソッドを使用して、デザイン パターンにシングルトン パターンを実装するなど、他の興味深いことを行うこともできます。クラスの各インスタンス化後に生成されるプロセスは __new__ を通じて制御されるため、__new__ メソッドをオーバーロードすることでシングルトン モードを簡単に実装できます。
class Singleton(object): def __new__(cls): # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象 if not hasattr(cls, 'instance'): cls.instance = super(Singleton, cls).__new__(cls) return cls.instance obj1 = Singleton() obj2 = Singleton() obj1.attr1 = 'value1' print obj1.attr1, obj2.attr1 print obj1 is obj2出力結果:
値1 値1
本当です