Reputation: 4992
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
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
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
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