Override __new__ doubts
Question: I will try to simplify the case here, when overriding `__new__` as bellow i
don't know the correct way of calling super `__new__` to do the job, am i
doing it ok or is there other way of doing this? `super().__new__(cls)` is not
producing correct results as i expected

i'm a python beginner, please be patient, i'm C++ fluent

    
    
    import weakref
    
    class A(str):
        def __init__(self,s):self.a=s
    class B(str):
        def __init__(self,s):self.b=s
    
    class P(A,B):
        manifest=weakref.WeakValueDictionary()
        def __new__(cls,a,b):
            o=P.manifest.get(a+b)
            if not o:
                print(a,b,super(P,cls))
                #i thought this first should be used because __init__ puts the values in
                #and we index the manifest with parameters [a+b]
                #o=super().__new__(cls)#produces unique results for all requests?!?
                #so i called like this and it works (either with a or b)
                o=super().__new__(cls,a)#why favoring a over b?
                #o=super().__new__(cls,b)#why favoring b over a?
                #o=super().__new__(cls,a,b)#its an error (of coz)
                P.manifest[a+b]=o
            print("using",id(o))
            return o
        def __init__(self,a,b):
            A.__init__(self,a)
            B.__init__(self,b)
    
    p=P("a","b")
    q=P("a","b")
    r=P("a","x")
    print(id(p),id(q),id(r))
    


Answer: I suspect (but I'm not sure) that you are trying to call `__new__` on both
your super classes, ie `A` and `B`. The best way to do that depends on a lot
of things.

The purpose of `P.__new__` is to return an instance of `P`. So that's what you
should create. This is indeed what `super().__new__(cls,a)` will do, so that
should work fine, however, you could also just call `str.__new__(cls, a)`
directly.

Usually you actually call `object.__new__`, but since you subclass from `str`
you can't do that, it will tell you that it's unsafe in this case.

If you do want to use `super()` (and there are cases when this is a good idea)
you should typically use it consistently in all of the classes, so it should
be used in `A` and `B` as well, and not only in `__new__` but also in
`__init__`

    
    
    class A(str):
        def __init__(self, s):
            super().__init__(s)
            self.a = s
    
        def __new__(cls, s):
            return super().__new__(cls, s)
    
    class B(str):
        def __init__(self, s):
            super().__init__(s)
            self.b = s
    
        def __new__(cls, s):
            return super().__new__(cls, s)
    

However, that becomes problematic here as you don't have the same function
profile, since P takes two parameters. This can be take as an indication that
your solution may not be the best one. Especially since P is a string that
takes two strings as parameters, that doesn't make much sense. In your
previous question, you talked about polymorphism, and this is a pattern that
break that polymorphism somewhat, as P doesn't have the same API as A and B,
and hence can't be used interchangeably.

The result is that I suspect that subclassing is the wrong solution here.
Also, I'm guessing you are trying to cache the objects so that creating new
objects with the same parameters will actually return the same object. I
suggest you instead use a factory method for that, instead of overriding
`__new__`.

