Разве не очевидно, что __new__
вернет объект типа C.
Вовсе нет. Допустимо следующее:
>>> class C:
... def __new__(cls):
... return "not a C"
... def __init__(self):
... print("Never called")
...
>>> C()
'not a C'
Когда вы переопределите __new__
, вы возможно вернете экземпляр cls
, но вы не обязательно к. Это полезно для определения фабричных классов, которые не создают экземпляры самих себя, а скорее экземпляры других классов.
Обратите внимание, что вы цитируете не совсем точно. x = C(32)
эквивалентно на первом этапе x = type.__call__(C, 32)
. Это type.__call__
вызывает C.__new__
, а затем решает, следует ли вызывать метод __init__
для возвращаемого значения.
Вы можете думать о type.__call__
как о чем-то вроде
def __call__(cls, *args, **kwargs):
obj = cls.__new__(cls, *args, **kwargs)
if isinstance(obj, cls):
obj.__init__(*args, **kwargs)
return obj
Применяя это к C
, мы видим, что obj
устанавливается в str
значение 'not a C'
, а не как экземпляр C
, так что 'not a C'.__init__
не вызывается перед возвратом строки.