On Thu, 26 Sep 2019 at 14:19, Peter Otten <__pete...@web.de> wrote:
>
> __init__ is called only if __new__ returns an instance of ClassB:
>
> """
>     /* If the returned object is not an instance of type,
>        it won't be initialized. */
>     if (!PyType_IsSubtype(Py_TYPE(obj), type))
>         return obj;
>
>     type = Py_TYPE(obj);
>     if (type->tp_init != NULL) {
>         int res = type->tp_init(obj, args, kwds);
> """
>
> https://github.com/python/cpython/blob/master/Objects/typeobject.c#L982

Interesting. I hadn't realised that was how it works. I tested with this:
"""
class A:
    def __new__(cls, arg):
        if arg == 'a':
            return object.__new__(A)
        elif arg == 'b':
            return object.__new__(B)
        elif arg == 'c':
            return object.__new__(C)
        elif arg == 'd':
            return D('foo')

    def __init__(self, arg):
        print('A.__init__', arg)

class B:
    def __init__(self, arg):
        print('B.__init__', arg)

class C(A):
    def __init__(self, arg):
        print('C.__init__', arg)

class D(A):
    def __new__(cls, arg):
        return object.__new__(cls)

    def __init__(self, arg):
        print('D.__init__', arg)

A('a')
A('b')
A('c')
A('d')
"""

Output:

$ python tmp.py
A.__init__ a
C.__init__ c
D.__init__ foo
D.__init__ d

So B.__init__ is never called and D.__init__ is called twice. I wonder
if there is a sensible way of organising this. Certainly I've always
taken the approach that you either use __new__ or __init__ and don't
mix them up.

--
Oscar
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to