Search code examples
pythonpropertiesgetter-setter

Use of property's getter in python


i was looking into properties and could not understand the use of getter.

Code :

class A:
    def __init__(self,p):
        self._p = p
    @property
    def p(self):
        return self._p
    @p.setter
    def p(self, value):
        self._p = value
    @p.getter
    def p(self):
        return self._p

so,i did the following

obj = A(10)
print(obj.p)

i got the following output:

10

So, i thought, @p.getter is called and the value of _q is returned.

But, i tried without @p.getter as below

class A:
    def __init__(self,p):
        self._p = p
    @property
    def p(self):
        return self._p
    @p.setter
    def p(self, value):
        self._p = value

And did the following

obj = A(10)
print(obj.p)

and even then i got the following output:

10

So, i was wondering, what is the actual use of @p.getter here, when @property it self was able to give us the value of _q


Solution

  • The @property decorator on a function creates a new property object and sets the decorated function as the getter. So within the same class, the @p.getter decorator is not very useful, no.

    However, the decorator is very useful if you wanted to override the getter in a subclass, or a reuse just the setter of the property on, but on a different class altogether:

    class Foo(object):
        @property
        def p(self):
            return self._p
    
        @p.setter
        def p(self, value):
            self._p = value
    
    class Bar(Foo):
        @Foo.p.getter
        def p(self):
            return self._p + 10
    

    or by copying the property object across to a different class:

    class NotASubclass(object):
        @Foo.p.getter
        def p(self):
            return self._p * 10
    

    Now Bar()and NotASubclass have a different getter for their property p, but both reuse the setter defined on the property for Foo().

    In both cases the @p.getter decorator creates a new property instance to store as an attribute of the class object, but their fset attributes all point to the same, single function object that acts as the setter. This is why it is enough to just reference @Foo.p.getter in either case; you only need the single property instance in the class namespace.

    Also see How does the @property decorator work? and Python overriding getter without setter