Python __new__ and __init__ multiple inheritance with string and second class

I am trying to create a derived class that inherits from both the str type and the second class. This is problematic because the str type does not just call __init__ , but the __new__ method __new__ of its immutability. I know that for __init__ and super, in order to work well, you need to have the same call structure to the end. However, the following implementation is performed:

 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 the 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__ to:

 def __new__(cls, *args, **kwargs): return super(base, cls).__new__(cls) 

but now I have changed the call structure, which I feel will cause me problems later in the line.

How to inherit a string and a second class ?

+4
source share
1 answer

You can't just do

 def __new__(cls, *args, **kwargs): return super(base, cls).__new__(cls) 

because it will cause an incorrect newline call (you will not pass the 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 may break something, if you use the base class as mixin for the class, the __new__ method takes more than one argument.

as an option, perhaps you should have a class inherited from str , but with an 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) 
+2
source

Source: https://habr.com/ru/post/1483644/


All Articles