I'm trying to create a derived class that inherits from both a str type and a second class. It's problematic since the str type doesn't simply call __init__, but the __new__ method due to its immutability. I know that for __init__ and super to work well, you need to have the same calling structure all the way down. However the following implementation fails:
class base(object):
    def __new__(cls, *args, **kwargs):
        print "NEW  BASE:", cls, args, kwargs
        return super(base, cls).__new__(cls, *args, **kwargs)
    def __init__(self, *args, **kwargs):
        print "INIT BASE", args, kwargs
class foo(base, str):
    def __new__(cls, *args, **kwargs):
        return super(foo, cls).__new__(cls, *args, **kwargs)
    def __init__(self, *args, **kwargs):
        super(foo, self).__init__(*args, **kwargs)
Here foo('cat') works with:
>> NEW  BASE: <class '__main__.foo'> ('cat',) {}
>> INIT BASE ('cat',) {}
but with an argument foo('cat', x=3), it fails:
>> NEW  BASE: <class '__main__.foo'> ('cat',) {'x': 3}
Traceback (most recent call last):
  File "inh.py", line 19, in <module>
    foo('cat', x=3)
  File "inh.py", line 12, in __new__
    return super(foo, cls).__new__(cls, *args, **kwargs)
  File "inh.py", line 4, in __new__
    return super(base, cls).__new__(cls, *args, **kwargs)
TypeError: str() takes at most 1 argument (2 given)
I can get this to work by changing the base.__new__ method to:
def __new__(cls, *args, **kwargs):
    return super(base, cls).__new__(cls)
but now I've changed the calling structure, which I feel will cause me problems later down the line.
How do I properly inherit from a string and a second class?
In Python a class can inherit from more than one class. If a class inherits, it has the methods and variables from the parent classes. In essence, it's called multiple inheritance because a class can inherit from multiple classes. This is a concept from object orientated programming.
Yes, you can do multiple inheritance. please note the order of class in ExampleSimMod matters. The's a great article about this.
Yes, Python supports multiple inheritance. Like C++, a class can be derived from more than one base classes in Python.
Use the super() Function By using the super() function, you do not have to use the name of the parent element, it will automatically inherit the methods and properties from its parent.
You can't just do
def __new__(cls, *args, **kwargs):
    return super(base, cls).__new__(cls)
because this will cause incorrect call for new of str (you will not pass allowed argument
>>> foo('t')
NEW  BASE: <class '__main__.foo'> ('t',) {}
INIT BASE ('t',) {}
''
You should do something like
def __new__(cls, *args, **kwargs):
    return super(base, cls).__new__(cls, *args[:1])
But this can broken something if You will use base class as mixin for class which __new__ method accept more than one argument.
as a option maybe You should have class inherited from str but with overridden new method:
class CarelessStr(str):
    def __new__(cls, *args, **kwargs):
        return super(CarelessStr, cls).__new__(cls, *args[:1])
class foo(base, CarelessStr):
    def __new__(cls, *args, **kwargs):
        return super(foo, cls).__new__(cls, *args, **kwargs)
    def __init__(self, *args, **kwargs):
        super(foo, self).__init__(*args, **kwargs)
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With