Beginnen wir mit Python-Dekoratoren.
Ein Python-Dekorator ist eine Funktion, mit der Sie einer bereits definierten Funktion einige zusätzliche Funktionen hinzufügen können.
In Python ist alles ein Objekt. Funktionen in Python sind erstklassige Objekte, dh sie können von einer Variablen referenziert, in die Listen aufgenommen, als Argumente an eine andere Funktion usw. übergeben werden.
Betrachten Sie das folgende Code-Snippet.
def decorator_func(fun):
def wrapper_func():
print("Wrapper function started")
fun()
print("Given function decorated")
# Wrapper function add something to the passed function and decorator
# returns the wrapper function
return wrapper_func
def say_bye():
print("bye!!")
say_bye = decorator_func(say_bye)
say_bye()
# Output:
# Wrapper function started
# bye
# Given function decorated
Hier können wir sagen, dass die Decorator-Funktion unsere say_hello-Funktion geändert und einige zusätzliche Codezeilen hinzugefügt hat.
Python-Syntax für Dekorateur
def decorator_func(fun):
def wrapper_func():
print("Wrapper function started")
fun()
print("Given function decorated")
# Wrapper function add something to the passed function and decorator
# returns the wrapper function
return wrapper_func
@decorator_func
def say_bye():
print("bye!!")
say_bye()
Lassen Sie uns alles abschließen als mit einem Fallszenario, aber vorher sprechen wir über einige Hoppla-Prinzipien.
Getter und Setter werden in vielen objektorientierten Programmiersprachen verwendet, um das Prinzip der Datenkapselung sicherzustellen (wird als Bündelung von Daten mit den Methoden angesehen, die mit diesen Daten arbeiten).
Diese Methoden sind natürlich der Getter zum Abrufen der Daten und der Setter zum Ändern der Daten.
Nach diesem Prinzip werden die Attribute einer Klasse privatisiert, um sie zu verbergen und vor anderem Code zu schützen.
Ja, @property ist im Grunde ein pythonische Methode, um Getter und Setter zu verwenden.
Python hat ein großartiges Konzept namens Eigenschaft, das das Leben eines objektorientierten Programmierers viel einfacher macht.
Nehmen wir an, Sie entscheiden sich für eine Klasse, in der die Temperatur in Grad Celsius gespeichert werden kann.
class Celsius:
def __init__(self, temperature = 0):
self.set_temperature(temperature)
def to_fahrenheit(self):
return (self.get_temperature() * 1.8) + 32
def get_temperature(self):
return self._temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
self._temperature = value
Refactored Code, hier ist, wie wir es mit Eigentum erreicht haben könnten.
In Python ist property () eine integrierte Funktion, die ein Eigenschaftsobjekt erstellt und zurückgibt.
Ein Eigenschaftsobjekt verfügt über drei Methoden: getter (), setter () und delete ().
class Celsius:
def __init__(self, temperature = 0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
def get_temperature(self):
print("Getting value")
return self.temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self.temperature = value
temperature = property(get_temperature,set_temperature)
Hier,
temperature = property(get_temperature,set_temperature)
hätte aufgeschlüsselt werden können als,
# make empty property
temperature = property()
# assign fget
temperature = temperature.getter(get_temperature)
# assign fset
temperature = temperature.setter(set_temperature)
Zu beachtender Punkt:
- get_temperature bleibt eine Eigenschaft anstelle einer Methode.
Jetzt können Sie durch Schreiben auf den Temperaturwert zugreifen.
C = Celsius()
C.temperature
# instead of writing C.get_temperature()
Wir können weiter gehen und die Namen get_temperature und set_temperature nicht definieren, da sie unnötig sind und den Klassennamensraum verschmutzen.
Der pythonische Weg , um mit dem oben genannten Problem umzugehen, ist die Verwendung von @property .
class Celsius:
def __init__(self, temperature = 0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
@property
def temperature(self):
print("Getting value")
return self.temperature
@temperature.setter
def temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self.temperature = value
Zu beachtende Punkte -
- Eine Methode zum Abrufen eines Werts wird mit "@property" dekoriert.
- Die Methode, die als Setter fungieren muss, ist mit "@ temperatur.setter" dekoriert. Wenn die Funktion "x" genannt worden wäre, müssten wir sie mit "@ x.setter" dekorieren.
- Wir haben "zwei" Methoden mit demselben Namen und einer unterschiedlichen Anzahl von Parametern "def Temperatur (Selbst)" und "Def Temperatur (Selbst, x)" geschrieben.
Wie Sie sehen können, ist der Code definitiv weniger elegant.
Lassen Sie uns nun über ein reales praktisches Szenario sprechen.
Angenommen, Sie haben eine Klasse wie folgt entworfen:
class OurClass:
def __init__(self, a):
self.x = a
y = OurClass(10)
print(y.x)
Nehmen wir nun weiter an, dass unsere Klasse bei Kunden beliebt wurde und sie sie in ihren Programmen verwendeten. Sie haben dem Objekt alle Arten von Aufgaben zugewiesen.
Und eines schicksalhaften Tages kam ein vertrauenswürdiger Kunde zu uns und schlug vor, dass "x" ein Wert zwischen 0 und 1000 sein muss. Dies ist wirklich ein schreckliches Szenario!
Aufgrund von Eigenschaften ist es einfach: Wir erstellen eine Eigenschaftsversion von "x".
class OurClass:
def __init__(self,x):
self.x = x
@property
def x(self):
return self.__x
@x.setter
def x(self, x):
if x < 0:
self.__x = 0
elif x > 1000:
self.__x = 1000
else:
self.__x = x
Das ist großartig, nicht wahr: Sie können mit der einfachsten Implementierung beginnen, die Sie sich vorstellen können, und Sie können später auf eine Eigenschaftsversion migrieren, ohne die Benutzeroberfläche ändern zu müssen! Eigenschaften sind also nicht nur ein Ersatz für Getter und Setter!
Sie können diese Implementierung hier überprüfen