So I am trying to override __new__ and let it exist as a factory to create
derived instances. After reading a bit on SO, I am under the impression that I should be calling __new__ on the derived instance as well.
BaseThing
class BaseThing:
    def __init(self, name, **kwargs):
        self.name = name
    # methods to be derived
ThingFactory
class Thing(BaseThing):
    def __new__(cls, name, **kwargs):
        if name == 'A':
           return A.__new__(name, **kwargs)
        if name == 'B':
           return B.__new__(name, **kwargs)        
    def __init__(self, *args, **kwargs):
        super().__init__(name, **kwargs)
   # methods to be implemented by concrete class (same as those in base)
A
class A(BaseThing):
    def __init__(self, name, **kwargs):
       super().__init__(name, **kwargs)
B
class B(BaseThing):
    def __init__(self, name, **kwargs):
       super().__init__(name, **kwargs)
 
what I am expecting was that it'd just work.
>>> a = Thing('A')
gives me TypeError: object.__new__(X): X is not a type object (str)
I am bit confused by this; when I just return a concrete instance of derived classes, it just worked. i.e.
def __new__(cls, name, **kwargs):
        if name == 'A':
           return A(name)
        if name == 'B':
           return B(name)
I don't think this is the correct way to return in __new__; it may duplicate the calls to __init__.
when I am checking signatures of __new__ in object it seems be this one:
@staticmethod # known case of __new__
def __new__(cls, *more): # known special case of object.__new__
    """ Create and return a new object.  See help(type) for accurate signature. """
    pass
I didn't expect this was the one; I'd expect it came with args and kwargs as well. I must have done something wrong here.
it seems to me that I need to inherit object directly in my base but could anyone explain the correct way of doing it?
 
    