Update:
Thanks for the responses. I think it finally helped make things click in my head now.
Python prescribes this workflow:
- start by just using properties and avoid over-engineering with boilerplate getter/setter
- when more logic is necessary, switch over to getter/setter using the @propertydecorator to maintain a consistent API to reduce refactoring
As oppose to these workflows:
- start out using getter/setter to avoid refactoring later.
- this adds unnecessary boilerplate code that might never be needed
 
or
- start out using properties
- switch to non-@propertygetter/setter when more logic is necessary
- refactor all dependent code to use getter/setter instead of properties
Thanks again for helping me understand these timeline of events and the awesome usefulness of @property.
If either of you want to add an answer, I'll accept it to close this out. Thanks again
Original:
I've been reading up on Python's @property decorator.
I understand that it is useful to allow library users to get properties like class.property while allowing library maintainers to refactor the getter logic behind the property-like interface much like a getter method.
What I don't understand is, why go through the hassle of using decorators to achieve an interface  that resembles a property, like class.property.  What is wrong with have a normal method like interface, like class.property()?
Is there something I'm missing? I don't understand why the extra parenthesis in the method call is problematic enough to warrant using a decorator?
Maybe the following code can help explain what I'm trying to get at better?:
class Class:
    def __init__(self, value):
        self._value = value
    def value(self):
        return self._value
print(Class('calling method').value())
class Class:
    def __init__(self, value):
        self._value = value
    @property
    def value(self):
        return self._value
print(Class('accessing property').value)
Is it because it makes setters prettier?
So instead of:
klass.set_value('some value')
you can have?:
klass.value = 'some value'
Like this example code?:
class Class:
    def __init__(self, value):
        self._value = value
    def value(self):
        return self._value
    def set_value(self, value):
        self._value = value
klass = Class('calling method')
klass.set_value('calling method2')
print(klass.value())
class Class:
    def __init__(self, value):
        self._value = value
    @property
    def value(self):
        return self._value
    @value.setter
    def value(self, value):
        self._value = value
klass = Class('accessing property')
klass.value = 'accessing property2'
print(klass.value)
Are the reasons to use the @property decorator purely to make the class interface more aesthetically pleasing?
I do think the interface ends up looking nicer, but I'm wondering if I'm missing something more.
Thank you for your time :)
