Wednesday 4 February 2015

Of Properties and property()

Cruising through Piazza I found someone asking a question about property(). While we have not seen it extensively in class (even being snuffed out of our lab), it is a very important function when wanting to exert more control on our object's attribute, thus limiting the control that a client might have over it. This is done for several reasons, one of them being security and another code consistency.

Examples:

  • For security: You have a variable that controls a game's score. You would not want someone to easily change the score by changing the value of the attribute!
  • For consistency: You have a method that involves, among other things, the division of two attributes. You would not want someone to change one of the attributes to 0 by mistake, crashing your program!

The person who posted the question was clearly unsure about how property() works, and the person who answered did not really expand much on its use, thus I decided to intervene and write some example code. Here is that example (with additional code):

class MagicNumber():
 '''
 A magic number with the attributes:
  x: int - The magic number
 '''
 
 def __init__(self):
  '''
  (MagicNumber) --> NoneType
  
  Initializes the magic number (self) with x as 42.
  '''
  #notice that we do not call it x, but rather _x
  #in order to keep it private
  self._x = 42

  def get_x(self):
  '''
  (MagicNumber) --> int
  
  Returns the magic number (x)
  '''
   #we simply return the value of x
   #or any thing we want
   #depends on what you want the client to see
   return self._x

  def set_x(self, num):
  '''
  (MagicNumber, int) --> NoneType
  
  If num is not zero, change the magic number (x) to num * 42.
  Otherwise, changes the value of the magic number to 42.
  '''
   #we can control how the attribute is modified
   #useful when we do not want certain values
   if num != 0:
    self._x = num * 42
   else:
    self._x = 42

  #important part!
  #we define here the properties of the attribute x
  #additionally, add a del_x and descriptor
  x = property(get_x, set_x)

#we do not address self._x, but rather self.x
>>> self.x = 1 #we just called the method set_x
>>> self.x #we just called the method get_x
42

No comments:

Post a Comment