The Python Game Book

code games. learn Python.

User Tools

Site Tools


Sidebar

Github:

en:glossary:p:property

property

also see @property decorator

class property (fget=None, fset=None, fdel=None, doc=None)
Return a property attribute.
fget is a function for getting an attribute value.
fset is a function for setting an attribute value.
fdel is a function for deleting an attribute value.
And doc creates a docstring for the attribute. https://docs.python.org/3/library/functions.html#property

other links:

Property is best explained by an example. First, a property can only exist inside a class. Unlike in other programming languages, in Python you generally do not need specific getter and setter methods to read / write an attribute.

getting and setting instance attributes

In this interactive example, a class Player with an attribute score is created and score can be manipulated (read and write) from outside the class:

>>>class Player:
       def __init__(self):
           score = 0
           
>>>a = Player()
>>>a.score 
0
>>>a.score = 14
>>>a.score
14

getter (read-only attribute)

Let's say you have an attribute for the Player class named xp for ExperiencePoints, but you have also a formula to calculate those Experiencepoints:

 xp = victories * 10 + solved_quests * 50 + bonus_xp
 

When your Player class already has attributes for victories, solved_quests and bounus_xp, it is therefore not necessary to create a new attributes for xp. It is only necessary to create a method to calculate the current value of xp on the fly:

>>> class Player:
	def __init__(self):
		self.bonus_xp = 0
		self.victories = 0
		self.quests_solved = 0
	def calculate_xp(self):
		return self.victories * 10 + self.quests_solved * 50 + self.bonus_xp

	
>>> a = Player()
>>> a.calculate_xp()
0
>>> a.victories = 5
>>> a.quests_solved = 2
>>> a.bonus_xp = 3
>>> a.calculate_xp()
153
>>> a.xp
Traceback (most recent call last):
  File "<pyshell#46>", line 1, in <module>
    a.xp
AttributeError: 'Player' object has no attribute 'xp'

In the example above, the method a.calculate_xp() works very well, however the direct attribute a.xp does not work, because the attribute xp simply does not exist

It would be nice to access xp directly using a.xp and this is exactly what property does: it provides a getter, setter and deleter method (and a docstring) for an attribute. At the moment, we are only interested in the getter:

There are 2 methods to write the property command:

  • by writing xp = property(calculate_xp) at the end of the class
  • by “decorating” the calculate_xp method with a @property decorator

Both variants do exactly the same:

without property() command with property decorator
class Player:
	def __init__(self):
		self.bonus_xp = 0
		self.victories = 0
		self.quests_solved = 0
	def calculate_xp(self):
        tmp = self.victories * 10 + self.quests_solved * 50
		return tmp + self.bonus_xp
    xp = property(calculate_xp)
class Player:
	def __init__(self):
		self.bonus_xp = 0
		self.victories = 0
		self.quests_solved = 0
    @property
	def xp(self):
        tmp = self.victories * 10 + self.quests_solved * 50
		return tmp + self.bonus_xp

In both cases, you have a read-only attribute .xp. Note that when using the decorator, the name of the method (xp) must be the same as the attribute that you want to control via the property.

Writeable attribute (setter)

If you want direct write access for an attribute (like typing a.xp = 500) but still be able to execute some checks and code before setting the attribute values, you need to provide the property command with an additional setter function.

Let's say the code should for some reason be able to set the Experience Point of the player to some given minimum amount, but without destroying the formular above. So to make sure the player has 500 xp total, the current xp must be calculated and the difference of 500 - xp is given to the player as bonus_xp. If the player already has 500 or more xp, he gets no additional xp.

A setter function makes the necessary calculations, and is given to the property command (or with an property decorator). As in the example above, both variants do exactly the same:

without property() command with property decorator
class Player:
	def __init__(self):
		self.bonus_xp = 0
		self.victories = 0
		self.quests_solved = 0
	def calculate_xp(self):
        tmp = self.victories * 10 + self.quests_solved * 50
		return tmp + self.bonus_xp
    def set_minimum_xp_to(self, value):
		if self.xp < value:
			self.bonus_xp += value - self.xp
    xp = property(calculate_xp, set_minimum_xp_to)
class Player:
	def __init__(self):
		self.bonus_xp = 0
		self.victories = 0
		self.quests_solved = 0
    @property
	def xp(self):
        tmp = self.victories * 10 + self.quests_solved * 50
		return tmp + self.bonus_xp
    @xp.setter
    def xp(self, value):
		if self.xp < value:
			self.bonus_xp += value - self.xp

Please note that when using the decorator, both the getter and the setter method must have exactly the same name (xp), the only difference is that the setter method accept an value parameter.

It is now possible to set the xp directly:

>>> a = Player()
>>> a.victories = 5
>>> a.quests_solved = 2
>>> a.xp
150
>>> a.xp = 200
>>> a.bonus_xp
50
>>> a.xp
200
>>> a.xp = 100
>>> a.xp
200

Please see the official python documentation at https://docs.python.org/3/library/functions.html#property for information about how to add an deleter and docstring

en/glossary/p/property.txt · Last modified: 2020/07/17 06:36 by horst