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 ?
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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.