Python trigger __new__ without __init__?

Viewed 62

I have a class A:

class A:
    def __new__(*args, **kwargs)
    def __init__(a1, a2)

Now I'd like to pass in a new argument a3 to create factory

class A:
    def __new__(*args, **kwargs):
       # Do sth with a3

    def __init__(a1, a2)

So here a3 is only used in __new__, but I realized I must pass in a3 into __init__ first to get it work, so that I need to modify __init__ into def __init__(a1, a2, a3) or def __init__(a1, a2, **kwargs). It's weird that I pass a3 but never use it in __init__

So basically here is there anyway I could just trigger __new__ without changing __init__?

1 Answers

__new__ and __init__ are called by type.__call__. Normally, when __new__ returns an instance of the target class, the metaclass calls __init__ on the result. You can override this behavior by changing the metaclass:

class MetaA(type):
    def __call__(cls, *args, **kwargs):
        obj = cls.__new__(cls, *args, **kwargs)
        # you can omit `__init__` entirely, or you can replicate
        # what `type` does, but strip the last positional argument:
        if isinstance(obj, cls):
            if len(args) > 2:
                args = args[:2]
            cls.__init__(obj, *args, **kwargs)
        return obj

class A(metaclass=MetaA):
    ...
Related