rawwar
rawwar

Reputation: 4992

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

Upvotes: 1

Views: 688

Answers (3)

Martijn Pieters
Martijn Pieters

Reputation: 1121992

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

Upvotes: 3

Aran-Fey
Aran-Fey

Reputation: 43166

The @property.getter decorator can be useful if you want to override a getter from a parent class in a subclass. It allows you to easily "copy" a property from the parent class and override only the getter, keeping the setter and deleter intact.

Example:

class Parent:
    @property
    def p(self):
        return 'parent'

    @p.setter
    def p(self, value):
        print('setting p to', value)

    @p.deleter
    def p(self):
        print('deleting p')

class Child(Parent):
    @Parent.p.getter
    def p(self):
        return 'child'

print(Parent().p)  # output: parent
print(Child().p)   # output: child
Child().p = 3      # output: setting p to 3
del Child().p      # output: deleting p

Upvotes: 4

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

As you've noticed, in this case, it's totally useless since you already passed the getter here

@property
def p(self):
    return self._p

but it might be useful for a couple corner cases at least, like dynamically redefining the getter for an existing property. I have to say I never had such a use case actually but well...

Upvotes: 0

Related Questions