How I ended up doing it.

class C(metaclass=ABCMeta):
    @property
    def x(self):
        ...

    @x.setter
    @abstractmethod
    def x(self, val):
        ...

class D(C):
    @C.x.setter
    def x(self, val):
        ...
Answer from jack sexton on Stack Overflow
🌐
Python
docs.python.org › 3 › library › abc.html
abc — Abstract Base Classes
This special case is deprecated, as the property() decorator is now correctly identified as abstract when applied to an abstract method: class C(ABC): @property @abstractmethod def my_abstract_property(self): ...
🌐
Python
bugs.python.org › issue39707
Issue 39707: Abstract property setter/deleter implementation not enforced, but documented as such - Python tracker
This issue tracker has been migrated to GitHub, and is currently read-only. For more information, see the GitHub FAQs in the Python's Developer Guide · This issue has been migrated to GitHub: https://github.com/python/cpython/issues/83888
🌐
GitHub
github.com › python › mypy › issues › 13649
Abstract settable properties are not fully supported · Issue #13649 · python/mypy
June 2, 2022 - import abc class Base(abc.ABC): @property @abc.abstractmethod def x(self) -> int: ... @x.setter @abc.abstractmethod def x(self, arg: int) -> None: ... class Child(Base): @property # E: Read-only property cannot override read-write property def x(self) -> int: ...
Author   sobolevn
🌐
Stack Overflow
stackoverflow.com › questions › 51798285 › python-override-abstractmethod-property-setter-and-getter-using-decorators-only › 51798390
Python override abstractmethod property setter and getter using decorators only - Stack Overflow
I'm following what is described at https://docs.python.org/3.4/library/abc.html#abc.abstractproperty but I keep getting · Traceback (most recent call last): File "test.py", line 30, in <module> test = B('bar') TypeError: Can't instantiate abstract class B with abstract methods foo · even though I implement both foo getter and setter in B. ... from abc import ABC, abstractmethod class A(ABC): @property @abstractmethod def foo(self): pass @foo.setter @abstractmethod def foo(self, val): pass def do_stuff(self): print(self.foo) class B(A): def __init__(self, val): self._foo = val @property def foo(self): return self._foo @A.foo.setter def foo(self, val): self._foo = val if __name__ == '__main__': test = B('bar') test.do_stuff() test.foo = 'barr' test.do_stuff()
Find elsewhere
🌐
Python.org
discuss.python.org › python help
Why does using property and abstractmethod not enforce properties in child? - Python Help - Discussions on Python.org
October 13, 2021 - Example: from abc import ABC, abstractmethod class AbstractExample(ABC): @property @abstractmethod def some_prop(self): pass class ConcreteExample(AbstractExample): def some_prop(self): return None c = ConcreteExample() # this does not raise
🌐
CodeFatherTech
codefather.tech › home › blog › create an abstract class in python: a step-by-step guide
Create an Abstract Class in Python: A Step-By-Step Guide
December 8, 2024 - Let’s add an attribute called speed to our abstract base class Aircraft and also property methods to read and modify its value. A way in Python to define property methods to read and modify the value of speed would be the following: class MyClass: ... ... @property def speed(self): return self.__speed @speed.setter def speed(self, value): self.__speed = value
🌐
Scaler
scaler.com › home › topics › abstract class in python
Abstract Class in Python - Scaler Topics
April 9, 2024 - As we have been told, properties are used in Python for getters and setters. Abstract property is provided by the abc module to force the child class to provide getters and setters for a variable in Python.
🌐
GitHub
github.com › python › mypy › issues › 3491
AttributeError with abstract property setter and "# type: ignore" · Issue #3491 · python/mypy
March 16, 2017 - from abc import ABC from abc import abstractmethod from typing import List class Test(ABC): @property def foo(self) -> List: """Getter""" @foo.setter # type: ignore @abstractmethod def foo(self, value: List) -> None: # type: ignore """Setter""" ... Traceback (most recent call last): File ".../bin/mypy", line 6, in <module> main(__file__) File ".../lib/python3.5/site-packages/mypy/main.py", line 46, in main res = type_check_only(sources, bin_dir, options) File ".../lib/python3.5/site-packages/mypy/main.py", line 93, in type_check_only options=options) File ".../lib/python3.5/site-packages/mypy/
Author   dokai
🌐
Everyday
everyday.codes › home › abstract classes and meta classes in python
Abstract Classes and Meta Classes in Python - everyday.codes
July 21, 2020 - class Car(AbstractVehicle): _engine = '' @property def engine(self): return self._engine @engine.setter def engine(self, new_engine): self._engine = new_engine.upper() car = Car() car.engine = 'v8 3.2 liters' print(car.engine) >> V8 3.2 LITERS · Take a closer look at the getter and the setter that is implemented here. Note that the setter changes the engine string to upper case. This is an example of using property to override default Python behaviour and its usage with abc.
🌐
Python.org
discuss.python.org › ideas
[abc] Add abstract attributes via `abstract` type-hint - Ideas - Discussions on Python.org
April 24, 2023 - Feature or enhancement Add a special generic type hint abstract, that allows specifying that subclasses must implement an attribute. from abc import ABC, abstract class Foo(ABC): myattr: abstract[int] # <- subcla…
🌐
The Teclado Blog
blog.teclado.com › python-abc-abstract-base-classes
How to Write Cleaner Python Code Using Abstract Classes
October 26, 2022 - Since animals often have different diets, we'll need to define a diet in our animal classes. Since all the animals are inheriting from Animal, we can define diet to be an abstract property. Besides diet, we'll make food_eaten property and it's setter will check if we are trying to feed the animal something that's not on it's diet.
Top answer
1 of 2
6

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.

2 of 2
0

For example, you can define the abstract getter, setter and deleter in Person abstract class, override them in Student class which extends Person abstract class as shown below. *@abstractmethod must be the innermost decorator otherwise error occurs:

from abc import ABC, abstractmethod

class Person(ABC):
    @property
    @abstractmethod # The innermost decorator
    def name(self): # Abstract getter
        pass

    @name.setter
    @abstractmethod # The innermost decorator
    def name(self, name): # Abstract setter
        pass

    @name.deleter
    @abstractmethod # The innermost decorator
    def name(self): # Abstract deleter
        pass

class Student(Person):
    def __init__(self, name):
        self._name = name
    
    @property
    def name(self): # Overrides abstract getter
        return self._name
    
    @name.setter
    def name(self, name): # Overrides abstract setter
        self._name = name
    
    @name.deleter
    def name(self): # Overrides abstract deleter 
        del self._name

Then, you can instantiate Student class and call the getter, setter and deleter as shown below:

obj = Student("John") # Instantiates "Student" class
print(obj.name) # Getter
obj.name = "Tom" # Setter
print(obj.name) # Getter
del obj.name # Deleter
print(hasattr(obj, "name"))

Output:

John
Tom
False

You can see my answer which explains more about abstract property.

🌐
Blue Book
lyz-code.github.io › blue-book › python_properties
Python Properties - The Blue Book
class Foo: @property def foo(self): return self._foo @foo.setter def foo(self, value): self._foo = value · We first decorate the foo method a as getter. Then we decorate a second method with exactly the same name by applying the setter attribute of the originally decorated foo method.
🌐
Python Module of the Week
pymotw.com › 2 › abc
abc – Abstract Base Classes - Python Module of the Week
import abc class Base(object): __metaclass__ = abc.ABCMeta @abc.abstractproperty def value(self): return 'Should never see this' @value.setter def value(self, newvalue): return class Implementation(Base): _value = 'Default value' @property def value(self): return self._value @value.setter def value(self, newvalue): self._value = newvalue i = Implementation() print 'Implementation.value:', i.value i.value = 'New value' print 'Changed value:', i.value · Notice that both methods in the Base and Implementation classes are named value(), although they have different signatures. $ python abc_abstractproperty_rw_deco.py Implementation.value: Default value Changed value: New value ·
Top answer
1 of 2
1

The problem is that neither the getter nor the setter is a method of your abstract class; they are attributes of the property, which is a (non-callable) class attribute. Consider this equivalent definition:

def status_getter(self):
    pass

def status_setter(self, value):
    pass

class Component(metaclass=abc.ABCMeta):
    # status = property(...)
    # status.__isabstractmethod__ = True
    status = abstractmethod(property(status_getter, status_setter))

Inheriting a property is quite different from inheriting a method. You are basically replacing the property, because your class itself does not have a reference to either the getter or the setter. Despite the name, abstractmethod does not actually make the property a method; it really does nothing more than add an attribute to whatever it is applied to and return the original value.

So, to ensure that a subclass provides a read/write property, what are you to do? Skip the decorator syntax, define the getter and setter as explicit abstract methods, then define the property explicitly in terms of those private methods.

class Component(metaclass=abc.ABCMeta):
    @abstractmethod
    def _get_status(self):
        pass

    @abstractmethod
    def _set_status(self, v):
        pass

    status = property(lambda self: self._get_status(), lambda self, v: self._set_status(self, v))

Or, you can make use of __init_subclass__ (which postdates abc; its purpose is to allow class initialization that is otherwise only possible via a metaclass).

class Component:
    def __init_subclass(cls, **kwargs):
        super().__init_subclass__(**kwargs)

        try:
            p = cls.status
        except AttributeError:
            raise ValueError("Class does not define 'status' attribute")

        if not isinstance(p, property):
            raise ValueError("'status' is not a property")

        if p.fget is None:
            raise ValueError("'status' has no getter")

        if p.fset is None:
            raise ValueError("'status' has no setter")

This is actually an improvement over abc, in my opinion. If a subclass fails to define a read/write status property, an exception will be raised when the class is defined, not just when you attempt to instantiate the class.

2 of 2
0
from abc import ABCMeta, abstractmethod

class Base(object):
    __metaclass__ = ABCMeta

    def __init__(self, val):
        self._foo = val

    @abstractmethod
    def _doStuff(self, signals):
        print ('Base does stuff')

    @abstractmethod
    def _get_foo(self):
        return self._foo

    @abstractmethod
    def _set_foo(self, val):
        self._foo = val + 'r'

    foo = property(_get_foo, _set_foo)

class floor_1(Base):
    __metaclass__ = ABCMeta

    def __init__(self, val):
        self._foo = val
        super(floor_1, self).__init__(val)

    def _doStuff(self, signals):
        print ('floor_1 does stuff')

    def _get_foo(self):
        return self._foo

    def _set_foo(self, val):
        #self._foo = val + 'r'
        super()._set_foo(val + 'r')

    foo = property(_get_foo, _set_foo)

class floor_2(floor_1):

    @property
    def foo(self):
        return self._foo

    @foo.setter
    def foo(self, val):
        self._foo = val + 'r'
        #super()._set_foo(val + 'r')

b1 = floor_1('bar')
# b1 = floor_2('bar')
print(b1.foo)
b1.foo = 'bar'
print(b1.foo)