Page 1 of 2
Attributes in Python are easy – until you want to do something more than just have an attribute that can reference an object. In this article we look at some of the real world practicalities of using attributes – we look at properties that work with get and set functions. This extract is from my new book with the subtitle "Something Completely Different".
Everything is an Object
Is now available as a print book: Amazon
- Hello Python World
- Variables, Objects and Attributes
- The Function Object
Extract - Function Objects
- Scope, Lifetime and Closure
Extract - Local and Global ***NEW
- Advanced Functions
Extract - Decorators
- Class Methods and Constructors
- Inside Class
- Advanced Attributes
Extract - Properties
- Custom Attribute Access
- Single Inheritance
- Multiple Inheritance
- Class and Type
- Type Annotation
- More Magic - Operator Overloading
Private Attributes and Name Mangling
final version in book
Private Attributes and Object Factories
final version in book
If you program in other object oriented language you will be wondering where getters and setters come into Python.
A getter and setter is the common name for mutator functions. A getter is a function that is automatically called to complete an assignment:
would automatically call geta which would return the value stored in temp.
would automatically call seta(temp) to store the value of temp in a.
If you haven’t encountered this idea before you might be wondering what the advantage is over direct access to the attribute?
The answer is that the functions can process the data and check that it is valid during the transaction. Most commonly, set checks that a value is valid, and get processes the data into an acceptable form.
Python supports getters and setters using an even more general facility called a descriptor object – more of this in Chapter 10. For the moment we will concentrate on how to implement getters and setters or a Python property rather than how it all works. The descriptor mechanism that is behind the built-in property function is very clever and well worth understanding.
The property built-in function is very simple:
class property(fget=None, fset=None, fdel=None, doc=None)
It takes three functions, fget the getter, fset the setter, and fdel a function that will remove the property. You can also include a docstring as the final parameter. The function returns a property attribute which can be added to a class and which implements the getter and setter protocol.
If you don’t include a function for fset you have a read-only property.
The standard way of creating a property is neat but not particularly instructive. To show how it works let’s do things differently.
All we need are three functions:
def setx(self, value):
self._x = value
Notice that each function uses self to determine the instance that it will be used with, and it assumes that the instance has an attribute _x to use to store the value. The variable that is used to actually store the value is often called a “backing variable”. Backing variables don’t just have to be variables, they can be arbitrarily complicated data structures - you can even use a database or a remote storage service over the net. This is one of the things that makes a property so useful.