13
class Singleton(type):
    def __init__(self, *args, **kwargs):
        print 'calling __init__ of Singleton class', self
        print 'args: ', args
        print 'kwargs: ', kwargs
        super(Singleton, self).__init__(*args, **kwargs)
        self.__instance = None
    def __call__(self, *args, **kwargs):
        print 'running __call__ of Singleton', self
        print 'args: ', args
        print 'kwargs: ', kwargs, '\n\n'
        if self.__instance is None:
            self.__instance = super(Singleton, self).__call__(*args, **kwargs)
        return self.__instance

class A(object):
    __metaclass__ = Singleton
    def __init__(self,a):
        print 'in __init__ of A:  ', self
        self.a = a
        print 'self.a: ', self.a

a=A(10)
b=A(20)

このコードは、 Python の __new__ と __init__ の使用に関する質問に対する Ben の回答からコピーしたものです。と少し修正しました。でも、流れがわからない。このコードが意図していることは、より高いレベルから理解していますが。しかし、内部でどのように機能するかはよくわかりません。

このコードを実行すると、次の出力が得られます:-

calling __init__ of Singleton class <class '__main__.A'>
args:  ('A', (<type 'object'>,), {'__module__': '__main__', '__metaclass__': <class '__main__.Singleton'>, '__init__': <function __init__ at 0x01F9F7B0>})
kwargs:  {}
running __call__ of Singleton <class '__main__.A'>
args:  (10,)
kwargs:  {}


in __init__ of A:   <__main__.A object at 0x01FA7A10>
self.a:  10
running __call__ of Singleton <class '__main__.A'>
args:  (20,)
kwargs:  {}

argskwargsforがどのように異なるのか理解できませ__init____call__。メタクラスを使用している間、このリンク ( What is a metaclass in Python?__new__ ) は、関数をメタクラスとして使用する方法を説明しています。しかし、私はどのように使用されているのか分かりません__call__

誰か流れを説明してくれませんか? これはつまり__new__、 、__call____init__が呼び出される優先順位と、誰が呼び出すかということです。

4

1 に答える 1

12

コードには が含まれていない__new__ため、それについてはほとんど言えません。

ただし、クラスの作成時にインスタンス化されるメタクラスを作成しますA。つまり、クラスAはオブジェクト自体であり、そのメタクラスのインスタンスですSingleton

それでは何が起こるか見てみましょう:

の環境が終了Aすると (そのメソッドが存在し、その dict も存在するなど)、クラスがメタクラスのインスタンスとして作成されます。基本的に、呼び出しは

A = Singleton('A', (object,), <the dict>)

where<the dict>は、クラスの名前空間を含む dict です (ここ__module__では 、__metaclass__および__init__)。

この への呼び出しでSingleton、 を呼び出すと、後で呼び出される新しいインスタンスを返すメソッドがsuper(Singleton, self).__call__(*args, **kwargs)呼び出されます。__new__.__init__

そのため、次のことが起こります。

calling __init__ of Singleton class <class '__main__.A'>
args:  ('A', (<type 'object'>,), {'__module__': '__main__', '__metaclass__': <class '__main__.Singleton'>, '__init__': <function __init__ at 0x01F9F7B0>})
kwargs:  {}

Aが構築されたら、インスタンス化して使用します。

a = A(10)

これは を呼び出しますAAは のインスタンスでSingletonあるため、Singleton.__call__が呼び出され、次のような効果があります。

running __call__ of Singleton <class '__main__.A'>
args:  (10,)
kwargs:  {}

Singleton.__call__を呼び出しtype.__call__、これはA.__new__および を呼び出しますA.__init__:

in __init__ of A:   <__main__.A object at 0x01FA7A10>
self.a:  10

その後、あなたは

b = A(20)

呼び出すSingleton.__call__

running __call__ of Singleton <class '__main__.A'>
args:  (20,)
kwargs:  {}

ここではsuper呼び出しが抑制され、古いオブジェクトが返されます。

于 2012-10-19T10:09:14.990 に答える