简体   繁体   中英

How can I implement a setter for an abstract property in Python?

I have an abstract class A which has a property for which I need to have a variable listener/setter:

class A(object, metaclass=abc.ABCMeta):
  @property
  @abc.abstractmethod
  def someData(self):
    pass

  # and several other functions which may or may not modify "someData"

The value to the field someData is being assigned in some of the derived classes. For the other derived classes, the field's value is defined by functions in A itself which are called by the derived class.

If I try doing something like this, ...

class A(object, metaclass=abc.ABCMeta):
  @property
  @abc.abstractmethod
  def someData(self):
    pass

  @someData.setter
  def someData(self, val):
    self.someData = val

... the setter is only called when the value of someData is changing within some function in A itself. If someData is assigned a value in one of the derived classes, it does not call the setter function.

How can I implement a setter for an abstract property (I need the setter to be called irrespective of whether the property is being assigned a value in one of the derived classes or in the abstract class)?

Use an alias that subclasses should not override, which calls a setter that subclasses should override:

class A(object, metaclass=abc.ABCMeta):
  @property
  @abc.abstractmethod
  def someData(self):
    pass

  @someData.setter
  def _setSomeData(self, val):
      self.setSomeData(val)

  def setSomeData(self, val):
    self._someData = val

Since self.someData is determined at runtime, not at compile-time, then as long as a subclass only overrides the someData() method, it will always get used as the 'actual' setter.

Usually when using this pattern, the externally-visible variable name is someData , but the internal name is _someData . Because _someData is not a @property, it can be get and set the normal way, without infinitely recurring. You would then proceed to also make a getter:

  @someData.getter
  def _getSomeData(self)
    return self.getSomeData()

  getSomeData(self):
    return self._someData

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM