If the requirement that it be a property is flexible, you could just define a static abstract method:
class X:
@staticmethod
@abstractmethod
def var():
pass
class Y(X):
@staticmethod
def var():
return [1, 2]
>>> Y.var()
[1, 2]
Answer from Ben Caine on Stack OverflowIf the requirement that it be a property is flexible, you could just define a static abstract method:
class X:
@staticmethod
@abstractmethod
def var():
pass
class Y(X):
@staticmethod
def var():
return [1, 2]
>>> Y.var()
[1, 2]
Maybe a variation on your solution could work - instead of using dict simply testing whether parent's and subclass static variables are the same object. It works for grandchildren and slots, but the tradeoff is that it will throw the exception if you override None with None, or other object with the same object, so it's not perfect.
class X:
var = [1,2]
def __init_subclass__(cls):
if X.var is cls.var:
raise NotImplementedError(
"Attribute '{}' has not been overriden in class '{}'" \
.format('var', cls.__name__)
)
Maybe I'm overlooking something crucial, but it worked in simple use cases.
Videos
I come from a C++ background, and I need to write an abstract base class, that inherits from abc. In this abstract base class, I would like to "declare" (this is C++ lingo, but I don't think variable declaration is a thing in Python) an uninstantiated variable, say `var`, which is initialized in the subclasses.
I'm wondering if there's any way to do this in Python?
Starting with Python 3.3, it is possible to combine @staticmethod and @abstractmethod, so none of the other suggestions are necessary anymore:
@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
@abstractstaticmethod has been deprecated since version 3.3 (but is still there in Python 3.14).
class abstractstatic(staticmethod):
__slots__ = ()
def __init__(self, function):
super(abstractstatic, self).__init__(function)
function.__isabstractmethod__ = True
__isabstractmethod__ = True
class A(object):
__metaclass__ = abc.ABCMeta
@abstractstatic
def test():
print 5
Python 3.3+
from abc import ABCMeta, abstractmethod
class A(metaclass=ABCMeta):
def __init__(self):
# ...
pass
@property
@abstractmethod
def a(self):
pass
@abstractmethod
def b(self):
pass
class B(A):
a = 1
def b(self):
pass
Failure to declare a or b in the derived class B will raise a TypeError such as:
TypeError: Can't instantiate abstract classBwith abstract methodsa
Python 2.7
There is an @abstractproperty decorator for this:
from abc import ABCMeta, abstractmethod, abstractproperty
class A:
__metaclass__ = ABCMeta
def __init__(self):
# ...
pass
@abstractproperty
def a(self):
pass
@abstractmethod
def b(self):
pass
class B(A):
a = 1
def b(self):
pass
Since this question was originally asked, python has changed how abstract classes are implemented. I have used a slightly different approach using the abc.ABC formalism in python 3.6. Here I define the constant as a property which must be defined in each subclass.
from abc import ABC, abstractmethod
class Base(ABC):
@classmethod
@property
@abstractmethod
def CONSTANT(cls):
raise NotImplementedError
def print_constant(self):
print(type(self).CONSTANT)
class Derived(Base):
CONSTANT = 42
This forces the derived class to define the constant, or else a TypeError exception will be raised when you try to instantiate the subclass. When you want to use the constant for any functionality implemented in the abstract class, you must access the subclass constant by type(self).CONSTANT instead of just CONSTANT, since the value is undefined in the base class.
There are other ways to implement this, but I like this syntax as it seems to me the most plain and obvious for the reader.
The previous answers all touched useful points, but I feel the accepted answer does not directly answer the question because
- The question asks for implementation in an abstract class, but the accepted answer does not follow the abstract formalism.
- The question asks that implementation is enforced. I would argue that enforcement is stricter in this answer because it causes a runtime error when the subclass is instantiated if
CONSTANTis not defined. The accepted answer allows the object to be instantiated and only throws an error whenCONSTANTis accessed, making the enforcement less strict.
This is not to fault the original answers. Major changes to the abstract class syntax have occurred since they were posted, which in this case allow a neater and more functional implementation.