For example, creating custom number types in following hierarchy
with logic in __new__
methods:
class Number:
def __new__(cls, value):
if isinstance(value, complex):
return Complex(value)
elif isinstance(value, (int, float)):
return Real(value)
else:
raise TypeError('Ну ты и мудак!!!')
def __init__(self, value):
self.value = value
class Complex(Number):
pass
class Real(Number):
def __new__(cls, value):
if isinstance(value, int):
return Int(value)
elif isinstance(value, float):
return Float(value)
else:
raise TypeError('Ты больше не можешь вести себя так!!!')
class Int(Real):
pass
class Float(Real):
pass
And then, creating Float
instance using Number
constructor:
number = Number(6.6)
assert isinstance(number, Float)
This code will raise RuntimeError
because of recursion limit. It is just example of desired behaviour. But I also tried to implement this using super
and it is seems I misunderstand the world.
Your Complex
, Float
and Int
classes do not have __new__
methods, so they inherit these from Number
; this is what is causing your infinite recursion.
You could test against the __class__
closure to see if you have a subclass or not:
class Number:
def __new__(cls, value):
if cls is not __class__:
# Subclass, create an instance (invokes object.__new__)
return super().__new__(cls)
if isinstance(value, complex):
return Complex(value)
elif isinstance(value, (int, float)):
return Real(value)
else:
raise TypeError('Ну ты и мудак!!!')
def __init__(self, value):
self.value = value
and do the same in Real
:
class Real(Number):
def __new__(cls, value):
if cls is not __class__:
# Subclass, create an instance
return super().__new__(cls, value)
if isinstance(value, int):
return Int(value)
elif isinstance(value, float):
return Float(value)
else:
raise TypeError('Ты больше не можешь вести себя так!!!')
Demo:
>>> class Number:
... def __new__(cls, value):
... if cls is not __class__:
... # Subclass, create an instance
... return super().__new__(cls)
... if isinstance(value, complex):
... return Complex(value)
... elif isinstance(value, (int, float)):
... return Real(value)
... else:
... raise TypeError('Ну ты и мудак!!!')
... def __init__(self, value):
... self.value = value
...
>>> class Real(Number):
... def __new__(cls, value):
... if cls is not __class__:
... # Subclass, create an instance
... return super().__new__(cls, value)
... if isinstance(value, int):
... return Int(value)
... elif isinstance(value, float):
... return Float(value)
... else:
... raise TypeError('Ты больше не можешь вести себя так!!!')
...
>>> class Complex(Number):
... pass
...
>>> class Int(Real):
... pass
...
>>> class Float(Real):
... pass
...
>>> number = Number(6.6)
>>> isinstance(number, Float)
True