In Python 3.6, Let's say I have an abstract class MyAbstractClass
from abc import ABC, abstractmethod
class MyAbstractClass(ABC):
@property
@abstractmethod
def myProperty(self):
pass
and a class MyInstantiatableClass
inherit from it. So how do I write to the property myProperty
on instantiation of an object from this class? I'd like to be able to both set and get myProperty
. Below doesn't work.
from MyAbstractClass import MyAbstractClass
class MyInstantiatableClass(MyAbstractClass):
def __init__(self, desiredValueOfMyProperty):
????
@myProperty.setter
def myProperty(self, desiredValueOfMyProperty): # value coming from __init__
self._myProperty = desiredValueOfMyProperty
And a main function, say,
from MyInstantiatableClass import MyInstantiatableClass
def main():
MyInstantiatableClass(3) # 3 is the desiredValueOfMyProperty for this instantiation
MyInstantiatableClass(5) # 5 is the desiredValueOfMyProperty for this instantiation
It seems there's a discrepancy here; using @property
along with @abstractmethod
doesn't seem to enforce classes that inherit from your abc to need to define both setter
and getter
. Using this:
@property
@abstractmethod
def myProperty(self):
pass
@myProperty.setter
@abstractmethod
def myProperty(self):
pass
and then providing an implementation only for the getter
in the class works and allows for instantiation:
@property
def myProperty(self):
return self._myProperty
This is due to the fact that only one name (myProperty
) appears in the namespace of the ABC, when you override in the base class, you only need to define this one name.
There's a way around that enforces it. You can create separate abstract methods and pass them on to property
directly:
class MyAbstractClass(ABC):
@abstractmethod
def getProperty(self):
pass
@abstractmethod
def setProperty(self, val):
pass
myAbstractProperty = property(getProperty, setProperty)
Providing an implementation for this abc now requires both getter
and setter
to have an implementation (both names that have been listed as abstractmethod
s in MyAbstractClass
namespace need to have an implementation):
class MyInstantiatableClass(MyAbstractClass):
def getProperty(self):
return self._Property
def setProperty(self, val):
self._Property = val
myAbstractProperty = property(getProperty, setProperty)
Implementing them is exactly the same as any old property. There's no difference there.