Благодаря @ juanpa.arrivillaga я придумал это решение, реализующее мой собственный дескриптор:
# myproperty.py
class MyProperty:
def __init__(self, fget=None, fset=None, key=None):
self.fget = fget
self.fset = fset
self.key = key
def __get__(self, obj, objtype=None):
if obj is None:
return self
if self.fget is None:
raise AttributeError("unreadable attribute")
return self.fget(obj)
def __set__(self, obj, value):
if self.fset is None:
raise AttributeError("can't set attribute")
perfrom_action(self.key, value)
self.fset(obj, value)
def getter(self, fget):
return type(self)(fget, self.fset, self.key)
def _setter(self, fset):
return type(self)(self.fget, fset, self.key)
def setter(self, key):
return type(self)(self.fget, self.fset, key=key)._setter
# foo_aspect.py
from myproperty import MyProperty
class FooAspect:
# ...
@MyProperty
def bar(self) -> int:
return self._bar
@bar.setter(key='bar')
def bar(self, value: int) -> None:
self._bar = value