does the @property decorator function as a getter?

Question:

i am new to python and i’m trying to understand the use of the ‘getter’. it’s use case is not obvious to me.
if i use a property decorator on a method and im able to return a certain value, what exactly would i use ‘getter’ for.

class Person:
    def __init__(self,name, age):
        self._name = name
        self._age = age
    
    @property
    def age(self):
        return self._age      

    
    @age.setter
    def age(self,new_age):
        if isinstance(new_age,int) and 18 < new_age < 120:
            self._age = new_age
Asked By: Moses Sunday

||

Answers:

The @property decorator adds a default getter on a given field in a Python class
that triggers a function call upon accessing a property.

The @property decorator turns the age() method into a “getter” for a read-only attribute with the same name. If want a “setter” then add @age.setter as you did in your question.

p = Person("John", 22)
print(p.age)

Output:

22
Answered By: CodeMonkey

The property type can take up to 4 separate arguments (a getter, a setter, a deleter, and a doc string) when instantiating it. The first argument is a function that will be used as a getter. The second is a function that will be used as a setter. You could have written your class as

class Person:
    def __init__(self,name, age):
        self._name = name
        self._age = age
    
    def _age_getter(self):
        return self._age

    def _age_setter(self, new_age):
        ...

    age = property(_age_getter, _age_setter)

This is cumbersome to write, so property objects have a number of methods for building the property up piece by piece. Using property as a simple decorator creates a read-only property with the decorated function as the getter.

# Equivalent to
#    def age(self):
#        return self._age
#    age = property(age)
@property
def age(self):
    return self._age

age.setter is a method of the property instance which creates a new property that is essentially a copy of age, but with its argument used to replace whatever setter the original property had. (Decorator syntax is why all the methods involved have to have the same name, so that we are constantly replacing the original property with the new, augmented property, rather than defining multiple similar properties with different names instead.)

@age.setter
def age(self, new_age):
    ...

Desugaring this requires the use of a temporary variable, to avoid losing the old value of age prematurely.

old_property = age
def age(self, new_age):
    ...
age = old_property.setter(age)

A silly, but legal, way of defining the property takes advantage of the fact that property can be defined with no arguments, and that there is a getter method that can be used as a decorator as well. (I don’t think I’ve ever seen it used in the wild, though.)

class Person:
    def __init__(self, name, age):
        ...

    age = property()

    @age.getter
    def age(self):
        ...

    @age.setter
    def age(self, new_age):
        ...

Note that the order in which we use getter, setter, (and deleter) methods doesn’t matter. The conventional order comes from the order in which property expects its positional arguments to be supplied, as well as the fact that new properties are virtually always defined by decorating the getter directly, rather than adding a getter to a property after it is created.

Answered By: chepner