нужно разобраться в потоке init, new и call

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__? и немного изменил его. Но я не осознаю потока. Хотя я понимаю с более высокого уровня, для чего предназначен этот код. Но, внутренне, как это работает, я не совсем уверен.

при запуске этого кода я получаю следующий вывод: -

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:  {}

Я не могу понять, как args и kwargs на __init__ и __call__ стань другим. При использовании метаклассов эта ссылка (что такое метаклассы в Python?) объяснил, как использовать __new__ и функция как метакласс. Но, я не понимаю, как __call__ используется.

может кто-нибудь объяснить поток? Под этим я подразумеваю, приоритет в котором __new__, __call__, __init__ называются и кто их называет?

1 ответов


ваш код не включает в себя __new__, так мало можно сказать об этом.

но вы создаете метакласс, который создается в классе time это. Другими словами, класс A сам объект и как таковой экземпляр его метакласса Singleton.

Итак, давайте посмотрим, что происходит:

после Aсреда завершена (ее методы существуют, ее дикт существует также,...), класс создается как экземпляр метакласс. По сути, вызов

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

здесь <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)

это A. A пример 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 вызов подавляется и возвращается старый объект.