[Python] Python abstract class shall force derived classes to initialize variable in __init__

Discussão em 'Python' iniciado por Stack, Abril 10, 2025.

  1. Stack

    Stack Membro Participativo

    I want to have an abstract class which forces every derived class to set certain attributes in its __init__ method.

    I've looked at several questions which did not fully solve my problem, specifically here or here. This looked promising but I couldn't manage to get it working.

    I assume my desired outcome could look like the following pseudo code:

    from abc import ABCMeta, abstractmethod


    class Quadrature(object, metaclass=ABCMeta):

    @someMagicKeyword #<==== This is what I want, but can't get working
    xyz

    @someMagicKeyword #<==== This is what I want, but can't get working
    weights


    @abstractmethod
    def __init__(self, order):
    pass


    def someStupidFunctionDefinedHere(self, n):
    return self.xyz+self.weights+n



    class QuadratureWhichWorks(Quadrature):
    # This shall work because we initialize xyz and weights in __init__
    def __init__(self,order):
    self.xyz = 123
    self.weights = 456

    class QuadratureWhichShallNotWork(Quadrature):
    # Does not initialize self.weights
    def __init__(self,order):
    self.xyz = 123


    Here are some of the things I have tried:

    from abc import ABCMeta, abstractmethod


    class Quadrature(object, metaclass=ABCMeta):

    @property
    @abstractmethod
    def xyz(self):
    pass


    @property
    @abstractmethod
    def weights(self):
    pass


    @abstractmethod
    def __init__(self, order):
    pass


    def someStupidFunctionDefinedHere(self, n):
    return self.xyz+self.weights+n



    class QuadratureWhichWorks(Quadrature):
    # This shall work because we initialize xyz and weights in __init__
    def __init__(self,order):
    self.xyz = 123
    self.weights = 456


    Then I try to create an instance:

    >>> from example1 import *
    >>> Q = QuadratureWhichWorks(10)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: Can't instantiate abstract class QuadratureWhichWorks with abstract methods weights, xyz
    >>>


    Which tells me to implement the methods, but I thought I said that these are properties?

    My current work-around has the flaw, that the __init__ method can be overwritten in the derived classes but for now this at least ensures (to me) that I always know that the requested properties are set:

    from abc import ABCMeta, abstractmethod


    class Quadrature(object, metaclass=ABCMeta):

    @abstractmethod
    def computexyz(self,order):
    pass


    @abstractmethod
    def computeweights(self,order):
    pass


    def __init__(self, order):
    self.xyz = self.computexyz(order)
    self.weights = self.computeweights(order)

    def someStupidFunctionDefinedHere(self, n):
    return self.xyz+self.weights+n



    class QuadratureWhichWorks(Quadrature):

    def computexyz(self,order):
    return order*123

    def computeweights(self,order):
    return order*456


    class HereComesTheProblem(Quadrature):

    def __init__(self,order):
    self.xyz = 123
    # but nothing is done with weights

    def computexyz(self,order):
    return order*123

    def computeweights(self,order): # will not be used
    return order*456


    But the problem is

    >>> from example2 import *
    >>> Q = HereComesTheProblem(10)
    >>> Q.xyz
    123
    >>> Q.weights
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    AttributeError: 'HereComesTheProblem' object has no attribute 'weights'


    How is this implemented correctly?

    Continue reading...

Compartilhe esta Página