Programmer's Python - Properties |
Written by Mike James | |||
Tuesday, 28 August 2018 | |||
Page 2 of 2
These three functions can be used to create a property object: myProperty=property(getx, setx, delx) The property object can now be set as an attribute of a class: class C: def __init__(self): self._x = None x = myProperty we also have to create the attribute that the property uses to store its value – the backing variable – using __init__. If you access x: c=C() c.x=1 print(c.x) del c.x in addition to changing and retrieving the value of x you will also see printed set, get and delete showing that the functions have been called. Notice that _x is not a private variable and it can be directly accessed so short circuiting the setters and getters, and getx, setx and delx can also be called directly. These are not desirable characteristics of a property. All of the internal workings of a property should be hidden and it should only be accessible via its getters and setters. A more usual way of creating a property is to include the functions within the class: class C: def __init__(self): self._x = None def getx(self): print("get") return self._x def setx(self, value): print("set") self._x = value def delx(self): print("delete") del self._x x =property(getx, setx, delx) This works in exactly the same way as the previous example but now the functions are attributes of the class. They are still directly accessible but this usually doesn’t matter. More importantly _x is still directly accessible. You could write: c=C() c._x=1 and bypass the set function. There a few subtle points to make clear before we move on. The first thing is that the property has to be defined on the class and not on an instance. In fact, you can see that the class property takes precedence over the instance as normally: c.x=1 would create a new attribute on the instance – this is the general Python principle that assignment is always to the local scope unless otherwise indicated. In this case assigning to x causes the lookup in the instances dictionary and then the class dictionary where the property takes over the assignment. If you try to create a property on an instance then the get and set functions are ignored and it is treated as if it was an attribute. Private PropertiesYou can use properties to implement a private property that is private in the sense that you cannot bypass the get and set functions to access it. ... final version in book Property as DecoratorThe property function takes three functions and returns a property object: myProperty=property(getx, setx, delx) However, as the parameters have defaults of None you can also use property as: myProperty=property(getx) to define a read only property. As this is a function which accepts a single function it can be used as a decorator: class C: @property def getx(self): return 10 which is exactly the same as: def getx(self): return 10 getx=property(getx) Notice that the name of the property is now the same as the name of the getter. You might think that this is the end of the story as far as decorators are concerned but the property object has two function methods – setter and deleter. These take a single function as a parameter and return a new property object with that function added as the setter or deleter. So we can continue to add functions to the property using decorators. For example: class C: @property def x(self): code to get property @x.setter def x(self,value): code to set property @x.deleter def x(self): code to delete property Notice that as decorators take a function and return a result using the same name you have to reuse the initial name. That is, the first decorator returns a property object referenced by x and this is the name used by the subsequent decorators. Summary
Programmer's Python
|
|||
Last Updated ( Tuesday, 28 August 2018 ) |