If your goal is to block the modification of a variable, you can use a property on an attribute without a setter. This will raise a exception if someone try to modify the value. Note that this do not ensure that the variable cannot be modified:
class Foo:
    def __init__(self):
        self._bar = 3
    @property
    def bar(self):
        return self._bar
foo = Foo()
foo._bar  # output 3
foo.bar  # output 3
foo.bar = 1 # raise an exception
foo._bar = 1  # _foo will be change to 1
If you just want to access and modify the attribute outside of the instance. You don't have to use any king of property:
class Foo:
    def __init__(self):
        self.bar = 3
foo = Foo()
foo.bar  # output 3
foo.bar = 1  # _foo will be change to 1
if you want to do some computation or validation of the input, you can use a get/set property:
class Foo:
    def __init__(self):
        self._bar = 3
    @property
    def bar(self):
        return self._bar + 1
    @bar.setter
    def bar(self, new_bar):
        assert isinstance(new_bar, int)
        self._bar = new_bar
foo = Foo()
foo.bar  # output 4
foo.bar = 1  # _foo will be change to 1
foo.bar = 'bar'  # raise assertion error