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