Python property() Function
The property() function allows to create a special type of attribute called a property for a class.
Syntax
property(fget, fset, fdel, doc)
property() Parameters
Python property() function parameters:
| Parameter | Condition | Description |
|---|---|---|
fget | Optional | A function for getting an attribute value |
fset | Optional | A function for setting an attribute value |
fdel | Optional | A function for deleting an attribute |
doc | Optional | The docstring of an attribute |
If any argument is passed as None or omitted, that operation is not supported.
property() Return Value
Python property() function returns:
- a property attribute from the given getter, setter, and deleter.
- a base property attribute that does not contain any getter, setter, or deleter, if no arguments are given.
Observations
attrib = property(fget, fset, fdel, doc) creates a new class attribute called attrib and defines the three methods as properties.
So:
- When you reference
x.attrib, Python calls thefgetmethod. - When you assign
x.attrib = value, Python calls thefsetmethod and passesvalueas an argument. - When you execute del
x.attrib, Python calls thefdelmethod.
Python uses the argument you passed as doc as the docstring of the attribute
If you do not specify the doc parameter, the getter method’s docstring becomes the docstring of the property.
Examples
Example 1: Basic Example
class Person:
def __init__(self, name):
self._name = name
# getter function
def get_name(self):
print('Getting name')
return self._name
# setter function
def set_name(self, value):
print('Setting name to ' + value)
self._name = value
# deleter function
def del_name(self):
print('Deleting name')
del self._name
# create the property
name = property(get_name, set_name, del_name, doc='name of the person')
The get_name(), set_name() and del_name() methods act like normal getter, setter and deleter until this line:
# create the property
name = property(get_name, set_name, del_name, doc='name of the person')
because it creates a new class attribute called name and defines the three methods as its properties.
So, now, when you refer to the name attribute of any Person object, Python actually calls the get_name() method:
p = Person('Ryan')
print(p.name) # Prints Getting name: Ryan
In the same way, when you assign a value to the name attribute, the set_name() method is called.
p.name = "Tom" # Output: Setting name to Tom
print(p.name) # Output: Getting name: Tom
And when you try to delete the name attribute, the del_name() method is called.
del p.name # Output: Deleting name
Moreover, you can access the docstring through the __doc__ attribute:
print(Person.name.__doc__) # Output: name of the person
Example 2: Computed Attributes
Properties can also be a way to define "computed attributes", i.e. attributes that are not actually stored, but are calculated dynamically on demand.
For example, let's define a class Rectangle that has a computed attribute for the area:
class Rectangle(object):
def __init__(self, width, height):
self.width = width
self.height = height
# computed attribute
def area(self):
return self.width * self.height
# make a property
area = property(area)
Then we can do:
r = Rectangle(10, 5) # Create a Rectangle object with width=10 and height=5
# and print the area
print(r.area) # Output: 50
output
50
Moreover, you can change width and height and the area property will be computed accordingly:
r = Rectangle(10, 5)
print(r.area) # Output: 50
r.width = 2
print(r.area) # Output: 10
r.height = 10
print(r.area) # Output: 20
output
50
10
20
If you don't specify a setter/getter/deleter property for an attribute and you try to use that property, then you will get an AttributeError exception.
For example:
r = Rectangle(10, 5)
r.area = 15
output
Traceback (most recent call last):
File "main.py", line 14, in <module>
r.area = 15
AttributeError: can't set attribute
Equivalent Method with @property decorator
Instead of using property(), a more elegant way is to use the Python decorator @property to assign the getter, setter, and deleter.
Decorators for an attribute called attr must be used in this way:
@propertydecorator goes before the getter method@attr.setterdecorator goes before the setter method@attr.deleterdecorator goes before the deleter method
For example, the Person class with decorators:
class Person:
def __init__(self, name):
self._name = name
# getter
@property
def name(self):
print('Getting name')
return self._name
# setter
@name.setter
def name(self, value):
print('Setting name to ' + value)
self._name = value
# deleter
@name.deleter
def name(self):
print('Deleting name')
del self._name
and so you can do:
p = Person('Tom')
# calls the getter
print('The name is:', p.name)
# calls the setter
p.name = 'Ryan'
# calls the deleter
del p.name
output
Getting name
The name is: Tom
Setting name to Ryan
Deleting name