Mit Python Property lassen sich At­tri­bu­ten aus einer Python-Klasse un­kom­pli­ziert Werte zuweisen. Ent­spre­chen­de Getter- oder Setter-Methoden werden bei der Ver­wen­dung von Python Property au­to­ma­tisch auf­ge­ru­fen.

Was genau ist Python Property und wofür wird es genutzt?

Python Pro­per­ties sind ein Pro­gram­mier­kon­strukt, das Ent­wi­ckeln­de innerhalb der ob­jekt­ori­en­tier­ten Pro­gram­mie­rung mit Python anwenden können. Pro­gram­mie­ren­de können damit Methoden de­fi­nie­ren, auf die im Anschluss wie auf Attribute zu­ge­grif­fen werden kann. Dies er­mög­licht einen in­tui­ti­ve­ren Zugriff auf die Attribute einer Klasse und macht außerdem das Aufrufen de­di­zier­ter Setter- und Getter-Methoden über­flüs­sig. Python Pro­per­ties ver­wan­deln Klas­sen­at­tri­bu­te in Pro­per­ties, die „Managed At­tri­bu­tes“ genannt werden.

Außerdem rea­li­siert eine Python Property eine Art Zu­griffs­kon­trol­le: Durch die Nutzung von Pro­per­ties kann si­cher­ge­stellt werden, dass andere Methoden nicht einfach auf die Daten des Attributs zugreifen und diese un­ge­wünscht verändern können.

Tipp

Wenn Sie Python nutzen, um ein Web­pro­jekt zu rea­li­sie­ren, lohnt sich auch ein Blick auf das prak­ti­sche Tool Deploy Now. Es er­mög­licht Ihnen, Ihren Code direkt via GitHub zu builden und zu deployen und ist somit ein enormer Ef­fi­zi­enz­vor­teil für Ihren Workflow.

Die Python-property()-Funktion

Für die Nutzung von Pro­per­ties können Ent­wi­ckeln­de sich der Python-property()-Funktion bedienen. Hierbei handelt es sich um eine Built-in-Funktion, die ohne den Import zu­sätz­li­cher Module genutzt werden kann. Python property() selbst ist in der Pro­gram­mier­spra­che C im­ple­men­tiert, wodurch eine optimale Per­for­mance ga­ran­tiert ist.

Die Syntax von Python property() sieht wie folgt aus:

property(fget=None, fset=None, fdel=None, doc=None)

Die Parameter der property()-Funktion sind optional. In der folgenden Über­sichts­ta­bel­le erfahren Sie, was die einzelnen Parameter bedeuten:

Parameter Bedeutung
fget Funktion, die den Wert des Attributs zu­rück­gibt (Getter-Methode)
fset Funktion, die es er­mög­licht, den Wert des Attributs zu setzen (Setter-Methode)
fdel Funktion, die angibt, wie das Attribut gelöscht werden soll
doc Python String, der die Property be­schreibt

Der Python Property Decorator

Die Nutzung der property()-Funktion ist nicht zwingend notwendig, um mit Pro­per­ties zu arbeiten. Häufig wird auf einen innerhalb von Python vor­de­fi­nier­ten Python Decorator zu­rück­ge­grif­fen, der es Ihnen erlaubt, eine Methode aus Ihrer Klasse als Property zu benutzen. Die Pro­gram­mier­spra­che un­ter­stützt drei ver­schie­de­ne De­ko­ra­to­ren in der bekannten @-Schreib­wei­se, damit Sie eine Property de­fi­nie­ren können:

  • @property: Kenn­zeich­net eine Methode Ihrer Klasse als Python Property
  • @.setter: Spe­zi­fi­ziert eine Setter-Methode, die den Wert einer Property setzt
  • @.deleter: Spe­zi­fi­ziert die Methode, die eine Property löscht

Python Property – Beispiel

Um sich die Funk­ti­ons­wei­se und den Nutzen von Python Pro­per­ties glei­cher­ma­ßen zu ver­an­schau­li­chen, hilft ein aus­führ­li­ches Code­bei­spiel. In folgendem Code­ab­schnitt wird zunächst eine Klasse namens „Hund“ mit dem Attribut „_name“ erstellt. Zu­ge­ge­be­ner­ma­ßen ist dieses Beispiel sehr kon­stru­iert und hat keinen realen Nutzen; dennoch ist es gut dazu geeignet, die Wir­kungs­wei­se von Python Pro­per­ties zu ver­an­schau­li­chen.

class Hund:
	def __init__(self):
		self._name = "Bello"

Sie sehen, dass der Kon­struk­tor keinen Parameter übergeben bekommt, der den Namen unseres Hundes spe­zi­fi­ziert. Statt­des­sen wird der Name des Hundes stan­dard­mä­ßig auf den Wert „Bello“ gesetzt. Sie können ein Objekt der Klasse also bei­spiels­wei­se mit folgender Codezeile erstellen:

hund = Hund()

Getter- und Setter-Methoden

Sie können Ihre Klasse durch spe­zi­fi­sche Getter- und Setter-Methoden erweitern. Das ist aus mehreren Gründen sinnvoll; vor allem die War­tungs­freund­lich­keit des Codes und das Einbauen zu­sätz­li­cher Funk­tio­na­li­tä­ten sind an dieser Stelle her­vor­zu­he­ben. Da es sich bei Namen stan­dard­mä­ßig um Zei­chen­ket­ten handelt, möchten wir in unserer Klasse außerdem si­cher­stel­len, dass auch tat­säch­lich ein Name in Form eines Strings übergeben wird. Hierzu schreiben wir die ent­spre­chen­de Funk­ti­ons­lo­gik in eine de­di­zier­te Setter-Methode und erweitern unsere obige Klas­sen­de­fi­ni­ti­on:

class Hund:
	def __init__(self):
		self._name = "Bello"
	
	def getName(self):
		return self._name
	def setName(self, name):
		if isinstance(name, str):
			self._name = name
		else:
			return

In der Setter-Methode namens „setName“ wird in einem Python-if-else-Statement überprüft, ob es sich bei dem über­ge­be­nen Parameter um einen String handelt. Ist dies der Fall, wird der Name gesetzt, ansonsten passiert nichts.

Außerdem haben wir eine Getter-Methode spe­zi­fi­ziert, die den Hamen des Hundes zu­rück­gibt.

Ein Objekt unserer Klasse mit dem Namen „Lassie“ kann wie folgt erstellt werden:

lassie = Hund()
lassie.setName("Lassie")
print(lassie.getName())

Der Output sieht wie folgt und somit auch wie gewünscht aus:

'Lassie'
Hinweis

Im Gegensatz zu anderen Pro­gram­mier­spra­chen kennt Python keine Mög­lich­keit, zwischen Klas­sen­at­tri­bu­ten zu un­ter­schei­den, die von außen direkt ohne Getter- oder Setter-Methoden genutzt werden dürfen (in anderen Pro­gram­mier­spra­chen werden diese Attribute oft als „public“ ge­kenn­zeich­net), und solchen, die von außen nicht ohne Weiteres verändert werden sollen (in anderen Pro­gram­mier­spra­chen „private“). Es ist daher Kon­ven­ti­on, die Va­ria­blen­na­men-Attribute, die nicht ohne Getter- und Setter-Methoden zum Einsatz kommen sollen, mit einem Un­ter­strich zu beginnen.

Python-property()-Funktion

Damit Sie auf einen ex­pli­zi­ten Funk­ti­ons­auf­ruf ver­zich­ten können, wenn Sie den Namen Ihres Python-Hundes verändern oder erfahren möchten, bedienen wir uns nun einer Python Property. Zu De­mons­tra­ti­ons­zwe­cken bauen wir außerdem je ein print-Statement in unsere Getter- und Setter-Methode ein.

class Hund:
	def __init__(self):
		self._name = "Bello"
	def getName(self):
		print("Getter-Methode aufgerufen")
		return self._name
	def setName(self, name):
		if isinstance(name, str):
			self._name = name
			print("Setter-Methode aufgerufen")
		else:
			return
	
	name = property(getName, setName)

Wie Sie sehen, haben wir für den Aufruf der property()-Funktion nichts weiter tun müssen, als eine neues Attribut namens „name“ zu erstellen (dieses Mal ohne führenden Un­ter­strich, weil es dank der Python Property ohne Weiteres von außen adres­siert werden darf) und diesem das Resultat unseres Funk­ti­ons­auf­rufs zu­zu­wei­sen. Als Parameter bekommt die property()-Funktion die bereits bekannten Getter- und Setter-Methoden.

Wenn Sie nun ein weiteres Objekt der Klasse mit den Namen „Snoopy“ erstellen, erkennen Sie bereits den Un­ter­schied:

snoopy = Hund()
snoopy.name = "Snoopy"
snoopy.name

Auf die Attribute der Klasse kann nun einfach mit der bekannten Punkt­no­ta­ti­on zu­ge­grif­fen werden. Ins­be­son­de­re der Output des Programms ist in­ter­es­sant:

Setter-Methode aufgerufen
Getter-Methode aufgerufen
'Snoopy'

Die Getter- und Setter-Methoden wurden, obwohl sie nicht explizit auf­ge­ru­fen wurden, in dem Moment aus­ge­führt, als die Zuweisung bzw. Abfrage des Namens vom Objekt „Snoopy“ mithilfe der Punkt­schreib­wei­se erfolgte. Das ist der Python Property zu verdanken.

Python Property Decorator

Denselben Effekt können Sie mithilfe der bereits erwähnten Funk­ti­ons­de­ko­ra­to­ren erzielen. In diesem Fall sieht der Bei­spiel­code wie folgt aus (achten Sie darauf, dass die beiden Methoden, die dekoriert werden, nun denselben Namen haben müssen):

class Hund:
	def __init__(self):
		self._name = "Bello"
	@property
	def name(self):
		print("Setter-Methode aufgerufen")
		return self._name
	@name.setter
	def name(self, name):
		if isinstance(name, str):
			self._name = name
			print("Getter-Methode aufgerufen")
		else:
			return

Erneut können Sie ein Objekt Ihrer Klasse erstellen und mithilfe der Punkt­schreib­wei­se das Attribut „name“ setzen und auslesen:

struppi = Hund()
struppi.name = "Struppi"
struppi.name

Der Output hat sich im Vergleich zur Nutzung der Python-property()-Funktion nicht verändert:

Setter-Methode aufgerufen
Getter-Methode aufgerufen
'Struppi'
Zum Hauptmenü