1

I have an abstract baseclass which uses a value whose implementation in different concrete classes can be either an attribute or a property:

from abc import ABC, abstractmethod


class Base(ABC):

    n: int

    
    def foo(self):
        ...
        a = ... + self.n

    @abstractmethod
    def bar(self):
        ...

class X(Base):
    def __init__(self, n: int):
      self.n = n

    def bar(self):
        ...

class Y(Base):

    @property
    def n(self) -> int:
        ...

    def bar(self):
        ...

The above code (outline, appropriately filled out), works at runtime, but mypy complains about the property in Y:

error: Signature of "n" incompatible with supertype "Base"

However, I can't remove the n: int because of foo, and I also can't put in an abstract property, because this breaks X. How should I declare the base class to make mypy happy with it?

Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
shaunc
  • 5,317
  • 4
  • 43
  • 58
  • 1
    Does this answer your question? [How to annotate attribute that can be implemented as property?](https://stackoverflow.com/questions/58349417/how-to-annotate-attribute-that-can-be-implemented-as-property) – joel Sep 14 '21 at 22:33

1 Answers1

1

Y can't be less flexible than Base and be a subclass, so you're likely going to need to make n an abstract property on Base then add a setter to X. It's not pretty, but it works (I think, I haven't checked)

class X(Base):
    def __init__(self, n: int):
        self._n = n

    @property
    def n(self) -> int:
        return self._n

    @n.setter
    def n(self, n: int) -> None:
        self._n = n

    ...
joel
  • 6,359
  • 2
  • 30
  • 55
  • Yup ... hmm... this is involved in a numerical computation, and wanted to numba.jitclass X eventually, but I realized that numba doesn't support ABC anyway, at least for the moment. When/if it does, I'll make "n" be a readonly property entirely... but your answer is correct for what I asked! – shaunc Sep 19 '21 at 00:58