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?
CodePudding user response:
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.