нужно разобраться в потоке 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, 'nn'
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 вызов подавляется и возвращается старый объект.