Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write to an abstract property in Python 3.4+

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
like image 988
Bora Avatar asked Nov 30 '25 12:11

Bora


1 Answers

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 abstractmethods 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.

like image 111
Dimitris Fasarakis Hilliard Avatar answered Dec 03 '25 01:12

Dimitris Fasarakis Hilliard



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!