Let's talk about how to make an automatically updating attribute in Python.
We have a
class Rectangle: def __init__(self, width, height): self.width = width self.height = height self.area = self.width * self.height
When we call this class, we'll get a
>>> rect = Rectangle(3, 4)
Rectangle object has a
height, and an
>>> rect.width 3 >>> rect.height 4 >>> rect.area 12
If we're considering acceptable to change the
height or an existing
Rectangle object, we might have problem.
If we change the
width of a
area won't change automatically:
>>> rect.width = 10 >>> rect.area 12
This happens because we only assigned the
area one time: in our initializer method.
When we first make a
Rectangle object, we set the
area in our
__init__ method, and that's it.
In a lot of programming languages, it's common to fix this problem by making a getter method.
Instead of an
area attribute we would make a method (maybe called
get_area or just
class Rectangle: def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height
When we access the
area method now, we'll see that it's a bound method:
>>> rect = Rectangle(3, 4) >>> rect.area <bound method Rectangle.area of <__main__.Rectangle object at 0x7f028eb3caf0>>
We can't just access
rect.area to get our area anymore.
We have to call the
area method in order to get a result:
>>> rect.area() 12
Now if we update the
width of our
>>> rect.width = 10
And call the
>>> rect.area() 40
Python will recompute the area and give us back the correct result.
In Python, writing getter methods is not common. Instead of using getter method, we tend to make a property.
We're using the
property decorator here:
class Rectangle: def __init__(self, width, height): self.width = width self.height = height @property def area(self): return self.width * self.height
That's called a decorator because of that
When we use the property decorator, it will make what was previously a method into a property.
Now if we make a
Rectangle object, just like before, and we access the
>>> rect = Rectangle(3, 4) >>> rect.area 12
Unlike before, we don't need to put parentheses after
In fact, we can't put parentheses.
Simply by accessing the
area attribute we get our answer.
So if we change the
width or the
height and we access
area again, it will recompute the area automatically:
>>> rect.width = 10 >>> rect.area 40
So Python isn't actually storing the
area attribute anywhere.
Instead, every time the
area attribute is accessed, it calls
area method and gives us back whatever the return value is.
And it does this automatically, simply because we accessed the
If you want to make an attribute on an object in Python that updates automatically you can use a property.
Subscribers get customized weekly recommendations for exercises and screencasts and access over 300 screencasts, exercises, and articles.
Save up to $108 per year if you subscribe by November 28.Save on Python screencasts and exercises
Need to fill-in gaps in your Python skills? I send regular emails designed to do just that.
Sign up for my Python tips emails and I'll share my favorite Python insights with you every couple weeks.
Need to fill-in gaps in your Python skills? I send weekly emails designed to do just that.