Search code examples
python-3.xinheritancesuper

Using super with inheritance from builtin type - different results with list


I'm trying to make a custom type that will behave just like builtin type but will also hold some additional information about the value. Code is like:

class Value:
    def __init__(self, value):
        super().__init__()

Then that would work:

addi_into = {x:y, ...}
base = (Value, int)
attr = {**dict(Value.__dict__), **addi_info}
_type = type('name', base, attr)
var = _type(1)

It behaves just as it was int, except I get access to additional info and methods in Value.

Only thing that does not work is when I do this:

addi_into = {x:y, ...}
base = (Value, list)
attr = {**dict(Value.__dict__), **addi_info}
_type = type('name', base, attr)
var = _type(['some', 'list'])

It breaks. There's no error, just that the list is empty.

Value methods and attributes are in place as expected.

The workaround is to have a special case for list,

because super().__init__(value) breaks it for other values:

class Value:
    def __init__(self, value):
        if type(value) == list: super().__init__(value)
        else: super().__init__()

Each type constructor (int, str, list...) I testef requires the value to be the first parameter so that kinda confuses me.

Can you suggest a more elegant way to implement this?

Or explain why this happens?


Solution

  • Immutable types (e.g. str, int) don't have their own __init__, and get the one inherited from object. Instead, they are fully initialized inside __new__. For these types you can omit the call to super().__init__() entirely and still get the correct result.

    To make this generic, you should probably check if __init__ of the base class is different from object.__init__, and only call it then.