9

I have a python property like this:

class Foo:

    @property
    def maxInputs(self):
        return self._persistentMaxInputs.value

    @maxInputs.setter
    def maxInputs(self, value):
        self._persistentMaxInputs.value = value

Currently, the value of maxInputs can be get and set by everyone.

However, I want to allow everyone to get the value of the maxInputs, but it should only be set inside of the Foo class.

So is there a way to declare a property with a private setter and a public getter?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
MorgoZ
  • 2,012
  • 5
  • 27
  • 54

2 Answers2

9

Python has no privacy model. Using underscores is only a convention, there is no access control. If you don't want the 'public' API to include a sett, then just remove the setter from your class and assign to self._persistentMaxInputs.value in your class code directly. You can make it a function if you want to limit the number of locations that need to remember this:

def _setMaxInputs(self, value):
    self._persistentMaxInputs.value = value

You can of course make that a separate property object, but then you'd have to forgo the decorator syntax:

def _maxInputs(self, value):
    self._persistentMaxInputs.value = value
_maxInputs = property(None, _maxInputs)

but now at least you can use self._maxInputs = value in your class code. This doesn't really offer that much of a syntax improvement however.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1

I use two properties in a case where I have a public property with private setter. It does create some redundant code, but I end up following the convention with decorators. See example below:

@property
def current_dir(self) -> str:
    """
    Gets current directory, analogous to `pwd`
    :return: Current working directory
    """
    return self._current_dir

@property
def _current_dir(self) -> None:
    return self._current_dir

@_current_dir.setter
def _current_dir(self, path:str) -> None:
    self._current_dir = path
gman112358
  • 29
  • 3
  • 3
    This would raise a `RecursionError` because the `_current_dir(self)` getter method is calling itself (`self._current_dir`). – Ollie Apr 16 '20 at 11:48