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