Search code examples
pythonooppropertiesgettersetter

Why do we need propertie's getter if property already does it's job in python?


Imagine two similar classes. First has property and getter and second one has only property. Property is doing the getter job already if we do not write getter explicitly. So why do we need to define getter?


class Test:

    def __init__(self):
        self._prop = 0

    @property
    def prop(self):
        print("property accessed")
        return self._prop

    @prop.getter
    def prop(self):
        print("getter accessed")
        return self._prop


class Test2:

    def __init__(self):
        self._prop = 0

    @property
    def prop(self):
        print("property accessed")
        return self._prop


if __name__ == "__main__":
    t = Test() 
    print(t.prop)
    et = Test2()
    print(et.prop)

# output
# getter accessed
# 0
# property accessed
# 0


Solution

  • The property class provides two ways to configure the getter, setter, and deleter methods.

    1. Passing functions as arguments when you create the property.
    2. Using the property's getter, setter, and deleter methods, each of which returns a new property with the corresponding fget, fset, or fdel overriden.

    For example, given three functions

    def get_value(self):
        ...
    
    def set_value(self, value):
        ...
    
    def delete_value(self):
        ...
    

    you write either

    p1 = property(get_value, set_value, delete_value)
    

    or

    # All arguments are optional
    p2 = property()
    p2 = p2.getter(get_value)
    p2 = p2.setter(set_value)
    p2 = p2.deleter(set_value)
    

    property, property.getter, property.setter, and property.deleter are all designed to allow them to be used as decorators.

    p2 = property()
    
    @p2.getter
    def p2(self):  # get_value
       ...
    
    @p2.setter
    def p2(self, value):  # set_value
        ...
    
    @p2.deleter
    def p2(self):  # del_value
        ...
    

    In ordinary usage, a hybrid approach is taken: the property is created and initialized with a getter in one step (the first argument is the getter to support this most common use-case of a read-only property), an optional setter and deleter provided when necessary.

    @property
    def p2(self):  # get_value
        ...
    

    So, the explicit use of property.getter is rare, but available. While all three methods could be called at any time to alter the behavior of an existing property, I don't think I've even seen them used other than for the intial configuration of a property.