I'm coming from C# world into python. In C#, I can use get and set to make updates to other object properties upon setting a value to a property, something like this:
private int _age;
private string _description;
public int Age
{
set
{
_age = value;
_description = (_age < 1500) ? "new": "old";
}
}
In python, I have the following class definition:
class Record(object):
age = 0
description = ""
<...a bunch of other properties...>
How can I set the description property of a Record object when I set the age property, in the same way as I can do it in C#, without having to write custom functions like get_age(self): and set_age(self):?
You should use the
propertydecorator for this:output:
When you use
@property, every time you userec.description, you are actually callingrec.description()and the return value of that call is used as the attributes value. This value gets recalculated every time you use the attribute.If there was only the
@propertydecorator, it would be impossible to set the attribute, as there is only a function that calculates the value. Luckily, we can use@age.setter. Every time the attribute is set (rec.age = value), this function is called.We can use of this to make the
descriptionattribute also being set when theageattribute is set.If you want to learn more about decorators, this page is a good start.
Another, less recommended, way to do this is using
__setattr__:The output is exactly the same.
Every time we set an attribute on an instance by using
instance.attrname = attrvalue, python callsinstance.__setattr__("attrname", attrvalue). Usually, this is the__setattr__function which is inherited fromobject, the class from which every class inherits.But when we override this function, we can choose our own behavior. In this case, it means that we also set the
descriptionattribute when the attribute 's name is"age".But, of course, we should still call the
object's__setattr__function to make that the attribute is actually set. We could do this directly usingobject.__setattr__(self, key, value), but a better way to do this is usingsuper.super()allows us to call functions of the class from which there is inherited. In this case it'sobject, but if you later on decide to letRecordinherit from another class that also defines__setattr__, that class's__setattr__will be called.