When running this code, the print displays the message "no number found in class A"
, although in fact it was not found in an object of class B.
The aim is to change only the Base class in such a way that, when inheriting from it, descendants create their own NotFoundError
exception inherited from Base.
class Base:
class NotFoundError(Exception):
pass
def __init__(self, numbers: list[int]):
self.numbers = numbers
def pop_by_val(self, number: int):
try:
self.numbers.remove(number)
except ValueError:
raise self.NotFoundError()
class A(Base):
pass
class B(Base):
pass
a = A([1, 2])
b = B([1, 2])
try:
a.pop_by_val(1)
b.pop_by_val(3)
except A.NotFoundError:
print("no number found in class A")
except B.NotFoundError:
print("no number found in class B")
I guess it can be fixed by some kind of init/new dunders' customization, but I haven't succeeded in my tries
There's no automatic definition of new, inherited class attributes, but you can define __init_subclass__
to define them for you.
class Base:
class NotFoundError(Exception):
pass
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
class NotFoundError(Base.NotFoundError):
pass
cls.NotFoundError = NotFoundError
def __init__(self, numbers: list[int]):
self.numbers = numbers
def pop_by_val(self, number: int):
try:
self.numbers.remove(number)
except ValueError:
raise self.NotFoundError()
(This is basically doing the same thing as @kindall's answer, but avoids using a metaclass. Prefer __init_subclass__
where possible to make it easier for your class to interact with more classes, as metaclasses don't compose well.)