Artificial Intelligence (AI)

8 Built-in Python Decorators to Write Elegant Code

Written by smirow

8 integrierte Python-Dekoratoren zum Schreiben eleganten Codes8 integrierte Python-Dekoratoren zum Schreiben eleganten Codes
Bild vom Herausgeber

Python ist mit seiner klaren und lesbaren Syntax eine weit verbreitete Programmiersprache auf hohem Niveau. Python ist für eine einfache Verwendung konzipiert, bei der Einfachheit und reduzierte Programmwartungskosten im Vordergrund stehen. Es verfügt über eine umfassende Bibliothek, die es Entwicklern erspart, Code von Grund auf neu zu schreiben, und ihre Produktivität steigert. Dekoratoren sind eine leistungsstarke Funktion von Python, die zur Eleganz des Codes beiträgt.

In Python ist ein Dekorator eine Funktion, mit der Sie das Verhalten einer anderen Funktion ändern können, ohne deren grundlegende Logik zu ändern. Es nimmt eine andere Funktion als Argument und gibt die Funktion mit erweiterter Funktionalität zurück. Auf diese Weise können Sie Dekoratoren verwenden, um mit nur wenigen Codezeilen zusätzliche Logik zu vorhandenen Funktionen hinzuzufügen und so die Wiederverwendbarkeit zu erhöhen. In diesem Artikel untersuchen wir acht integrierte Python-Dekoratoren, die Ihnen dabei helfen können, eleganteren und wartbareren Code zu schreiben.

8 integrierte Python-Dekoratoren zum Schreiben eleganten Codes8 integrierte Python-Dekoratoren zum Schreiben eleganten Codes
Bild vom Herausgeber

DER @atexit.register Der Dekorator wird verwendet, um eine Funktion zu registrieren, die am Ende des Programms ausgeführt werden soll. Diese Funktion kann verwendet werden, um jede Aufgabe auszuführen, wenn das Programm kurz vor dem Beenden steht, sei es aufgrund einer normalen Ausführung oder eines unerwarteten Fehlers.

Beispiel:

import atexit

# Register the exit_handler function
@atexit.register
def exit_handler():
    print("Exiting the program. Cleanup tasks can be performed here.")

# Rest of the program
def main():
    print("Inside the main function.")
    # Your program logic goes here.

if __name__ == "__main__":
    main()

Ausgehen:

Inside the main function.
Exiting the program. Cleanup tasks can be performed here.

In der obigen Implementierung @atexit.register wird oberhalb der Funktionsdefinition erwähnt. Es definiert die exit_handler() Funktion als Ausgabefunktion. Im Wesentlichen bedeutet dies, dass jedes Mal, wenn das Programm seinen Endpunkt erreicht, sei es durch die normale Ausführung oder aufgrund eines unerwarteten Fehlers, der zu einem vorzeitigen Beenden führt, das exit_handler() Die Funktion wird aufgerufen.

DER @dataclasses.dataclass ist ein leistungsstarker Dekorator, der zum automatischen Generieren allgemeiner Spezialmethoden für Klassen wie „__init__“, „__repr__“ und andere verwendet wird. Es hilft Ihnen, saubereren und prägnanteren Code zu schreiben, da es nicht mehr erforderlich ist, Standardmethoden zum Initialisieren und Vergleichen von Instanzen Ihrer Klasse zu schreiben. Es kann auch dazu beitragen, Fehler zu vermeiden, indem sichergestellt wird, dass gängige Spezialmethoden in Ihrer gesamten Codebasis konsistent implementiert werden.

Beispiel:

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int


point = Point(x=3, y=2)
# Printing object
print(point)

# Checking for the equality of two objects
point1 = Point(x=1, y=2)
point2 = Point(x=1, y=2)
print(point1 == point2)

Ausgehen:

DER @dataclass Der über der Point-Klassendefinition angewendete Decorator signalisiert Python, das Standardverhalten zum Generieren spezieller Methoden zu verwenden. Dadurch wird automatisch das erstellt __init__ Methode, die Klassenattribute wie x und y initialisiert, wenn das Objekt instanziiert wird. Dadurch können Instanzen wie point erstellt werden, ohne auf explizite Codierung zurückgreifen zu müssen. Darüber hinaus ist die __repr__ Auch die Methode, die für die Bereitstellung einer String-Darstellung der Objekte verantwortlich ist, wird automatisch angepasst. Dadurch wird sichergestellt, dass ein Objekt, beispielsweise ein Punkt, beim Drucken eine klare und geordnete Darstellung erhält, wie im Ergebnis gezeigt: Point(x=3, y=2). Darüber hinaus ergibt der Vergleich der Gleichheit (==) zwischen zwei Instanzen, Punkt1 und Punkt2, „True“. Dies ist bemerkenswert, da Python standardmäßig anhand des Speicherorts prüft, ob Gleichheit vorliegt. Im Kontext von Datenklassenobjekten wird die Gleichheit jedoch durch die darin enthaltenen Daten bestimmt. Tatsächlich generiert der @dataclass-Dekorator eine __eq__ Methode, die die Gleichheit der in Objekten vorhandenen Daten überprüft, anstatt denselben Speicherort zu überprüfen.

DER @enum.unique Der im Enum-Modul enthaltene Decorator wird verwendet, um sicherzustellen, dass die Werte aller Mitglieder einer Enumeration eindeutig sind. Dadurch wird verhindert, dass versehentlich mehrere Aufzählungsmitglieder mit demselben Wert erstellt werden, was zu Verwirrung und Fehlern führen kann. Wenn doppelte Werte gefunden werden, a Wertfehler ist notiert.

Beispiel:

from enum import Enum, unique

@unique
class VehicleType(Enum):
    CAR = 1
    TRUCK = 2
    MOTORCYCLE = 3
    BUS = 4

# Attempting to create an enumeration with a duplicate value will raise a ValueError
try:
    @unique
    class DuplicateVehicleType(Enum):
        CAR = 1
        TRUCK = 2
        MOTORCYCLE = 3
        # BUS and MOTORCYCLE have duplicate values
        BUS = 3
except ValueError as e:
    print(f"Error: {e}")

Ausgehen:

Error: duplicate values found in : BUS -> MOTORCYCLE

In der obigen Implementierung haben „BUS“ und „MOTORRAD“ den gleichen Wert „3“. Folglich ist die @unique Der Dekorator löst einen ValueError mit der Meldung aus, dass doppelte Werte gefunden wurden. Sie können denselben Schlüssel auch nicht mehr als einmal verwenden oder verschiedenen Mitgliedern denselben Wert zuweisen. Auf diese Weise werden doppelte Werte für mehrere Aufzählungsmitglieder vermieden.

DER partial Decorator ist ein leistungsstarkes Werkzeug zum Erstellen von Teilfunktionen. Mit Teilfunktionen können Sie einige Argumente der ursprünglichen Funktion vordefinieren und eine neue Funktion mit diesen bereits ausgefüllten Argumenten generieren.

Beispiel:

from functools import partial

# Original function
def power(base, exponent):
    return base ** exponent

# Creating a partial function with the exponent fixed to 2
square = partial(power, exponent=2)

# Using the partial function
result = square(3)
print("Output:",result)

Ausgehen:

In der obigen Implementierung haben wir eine „Potenz“-Funktion, die zwei Argumente „Basis“ und „Exponent“ akzeptiert und das Ergebnis der mit dem Exponenten potenzierten Basis zurückgibt. Wir haben mit der Originalfunktion eine Teilfunktion namens „Quadrat“ erstellt, deren Exponent auf 2 vordefiniert ist. Auf diese Weise können wir die Funktionalität der Originalfunktionen um a erweitern partial Dekorateur.

DER @singledisptach Der Dekorator wird zum Erstellen allgemeiner Funktionen verwendet. Sie können damit verschiedene Implementierungen von Funktionen mit demselben Namen, aber unterschiedlichen Argumenttypen definieren. Dies ist besonders nützlich, wenn Sie möchten, dass sich Ihr Code für verschiedene Datentypen unterschiedlich verhält.

Beispiel:

from functools import singledispatch

# Decorator
@singledispatch
def display_info(arg):
    print(f"Generic: {arg}")

# Registering specialized implementations for different types
@display_info.register(int)
def display_int(arg):
    print(f"Received an integer: {arg}")

@display_info.register(float)
def display_float(arg):
    print(f"Received a float: {arg}")

@display_info.register(str)
def display_str(arg):
    print(f"Received a string: {arg}")

@display_info.register(list)
def display_sequence(arg):
    print(f"Received a sequence: {arg}")

# Using the generic function with different types
display_info(39)             
display_info(3.19)          
display_info("Hello World!")
display_info([2, 4, 6])     

Ausgehen:

Received an integer: 39
Received a float: 3.19
Received a string: Hello World!
Received a sequence: [2, 4, 6]

In der obigen Implementierung haben wir zunächst die generische Funktion erweitert display_info() Verwendung der @singledisptach decorator erstellt und dann seine Implementierung für int, float, string und list separat registriert. Die Ausgabe zeigt die Funktionsweise von display_info() für unterschiedliche Datentypen.

DER @classmethod ist ein Dekorator, der zum Definieren von Klassenmethoden innerhalb der Klasse verwendet wird. Klassenmethoden sind an die Klasse und nicht an das Klassenobjekt gebunden. Der Hauptunterschied zwischen statischen Methoden und Klassenmethoden ist ihre Interaktion mit dem Klassenstatus. Klassenmethoden haben Zugriff auf den Klassenstatus und können ihn ändern, während statische Methoden nicht auf den Klassenstatus zugreifen und unabhängig davon arbeiten können.

Beispiel:

class Student:
    total_students = 0

    def __init__(self, name, age):
        self.name = name
        self.age = age
        Student.total_students += 1

    @classmethod
    def increment_total_students(cls):
        cls.total_students += 1
        print(f"Class method called. Total students now: {cls.total_students}")

# Creating instances of the class
student1 = Student(name="Tom", age=20)
student2 = Student(name="Cruise", age=22)

# Calling the class method
Student.increment_total_students()  #Total students now: 3

# Accessing the class variable
print(f"Total students from student 1: {student1.total_students}")
print(f"Total students from student 2: {student2.total_students}")

Ausgehen:

Class method called. Total students now: 3
Total students from student 1: 3
Total students from student 2: 3

In der obigen Implementierung ist die Student Klasse hat total_students als Klassenvariable. DER @classmethod Der Dekorator wird verwendet, um die zu definieren increment_total_students() Klassenmethode zum Erhöhen der total_students Variable. Jedes Mal, wenn wir eine Instanz der Student-Klasse erstellen, wird die Gesamtzahl der Studenten um eins erhöht. Wir haben zwei Instanzen der Klasse erstellt und diese dann mit der Klassenmethode geändert total_students variabel zu 3was sich auch in den Klasseninstanzen widerspiegelt.

DER @staticmethod Decorator wird verwendet, um statische Methoden innerhalb einer Klasse zu definieren. Statische Methoden sind Methoden, die aufgerufen werden können, ohne eine Instanz der Klasse zu erstellen. Statische Methoden werden häufig verwendet, wenn sie nicht auf objektbezogene Parameter zugreifen müssen und sich eher auf die Klasse als Ganzes beziehen.

Beispiel:

class MathOperations:
    @staticmethod
    def add(x, y):
        return x + y

    @staticmethod
    def subtract(x, y):
        return x - y

# Using the static methods without creating an instance of the class
sum_result = MathOperations.add(5, 4)
difference_result = MathOperations.subtract(8, 3)

print("Sum:", sum_result)            
print("Difference:", difference_result)

Ausgehen:

In der obigen Implementierung haben wir verwendet @staticmethod um eine statische add()-Methode für die Klasse „MathOperations“ zu definieren. Wir haben die beiden Zahlen „4“ und „5“ hinzugefügt, was zu „9“ führt, ohne eine Instanz der Klasse zu erstellen. Subtrahieren Sie auf ähnliche Weise die beiden Zahlen „8“ und „3“, um „5“ zu erhalten. Auf diese Weise können statische Methoden generiert werden, um Hilfsfunktionen auszuführen, die nicht den Status einer Instanz erfordern.

DER @property Decorator wird verwendet, um Getter-Methoden für Klassenattribute zu definieren. Getter-Methoden sind Methoden, die den Wert eines Attributs zurückgeben. Diese Methoden werden zur Datenkapselung verwendet, die angibt, wer auf die Details der Klasse oder Instanz zugreifen kann.

Beispiel:

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        # Getter method for the radius.
        return self._radius

    @property
    def area(self):
        # Getter method for the area.
        return 3.14 * self._radius**2

# Creating an instance of the Circle class
my_circle = Circle(radius=5)

# Accessing properties using the @property decorator
print("Radius:", my_circle.radius)          
print("Area:", my_circle.area)  

Ausgehen:

In der obigen Implementierung verfügt die Klasse „Circle“ über ein „Radius“-Attribut. Wir verwendeten @property um Getter-Methoden für Radius und Fläche zu konfigurieren. Es bietet Benutzern der Klasse eine klare und konsistente Schnittstelle für den Zugriff auf diese Attribute.

In diesem Artikel werden einige der vielseitigsten und funktionalsten Dekoratoren vorgestellt, mit denen Sie Ihren Code flexibler und lesbarer machen können. Mit diesen Dekoratoren können Sie die Funktionalität der ursprünglichen Funktion erweitern, um sie organisierter und weniger fehleranfällig zu machen. Sie sind wie magische Schlüssel, die dafür sorgen, dass Ihre Python-Programme ordentlich aussehen und reibungslos funktionieren.

Kanwal Mehreen Kanwal ist ein Ingenieur für maschinelles Lernen und technischer Autor mit einer Leidenschaft für Datenwissenschaft und die Schnittstelle zwischen KI und Medizin. Sie ist Mitautorin des E-Books „Maximizing Productivity with ChatGPT“. Als Google Generation Scholar 2022 für APAC setzt sie sich für Vielfalt und akademische Exzellenz ein. Sie ist außerdem als Teradata Diversity in Tech Fellow, Mitacs Globalink Research Fellow und Harvard WeCode Fellow anerkannt. Kanwal ist ein starker Befürworter von Veränderungen und hat FEMCodes gegründet, um Frauen in MINT-Bereichen zu stärken.

About the author

smirow

Leave a Comment