TLDR: вы неправильно перезаписываете __init__
вместо __new__
.
class XBytes(bytes):
__slots__ = 'x', # avoid arbitrary attributes
def __new__(cls, bs: bytes, x: int = 0):
# call original __new__ with expected signature
self = super().__new__(cls, bs)
self.x = x
return self
Типы Python канонически имеют два метода, которые используются при построении объекта:
__new__
создает объект ("конструктор")
__init__
создает состояние («инициализатор»)
Примечательно, что оба они вызываются при создании объекта. Вы можете думать о создании экземпляра Class
(например, Class(1, 2, 3)
) как эквивалент этого:
def new(cls, *args, **kwargs):
"""same as ``cls(*args, **kwargs)``"""
self = cls.__new__(cls, *args, **kwargs)
if isinstance(self, cls):
cls.__init__(self, *args, **kwargs)
Обратите внимание, как __new__
создает объект, в то время как __init__
только изменяет его. Для неизменяемых типов необходимо переопределить __new__
, поскольку они не могут быть изменены.
Если вы переопределите __init__
, подпись __new__
не изменится! При вызове inheritest(b'foobar', 3)
аргументы b'foobar', 3
передаются исходному bytes.__new__
. Это происходит до того, как будет вызван ваш пользовательский __init__
, таким образом, никогда не вызовет print
.